
过滤器是Servlet体系里的“守门人”:它能在请求到达页面或Servlet前先“查身份”——看看Session里有没有登录用户的信息,没有的话直接跳转到登录页,根本不给访问机会。更妙的是,不用在每个页面重复写判断代码,一次配置就能全局生效,省事儿又靠谱。
这篇文章就手把手教你实现这个“安全门”:从创建Filter类、编写拦截逻辑,到配置web.xml或用注解让过滤器生效,每一步都讲得明明白白。哪怕是刚学Servlet+JSP的新手,跟着走也能快速搞定——再也不用怕未登录用户乱闯页面啦!现在就跟着做,给你的项目加道“保险”吧~
你有没有过这种糟心经历?做Servlet+JSP的小项目——比如校园社团管理系统、小型电商后台,用户没登录直接输个http://localhost:8080/user/center.jsp
,就能绕过登录页闯进个人中心,甚至能改别人的信息?我去年帮学弟做毕设时就碰到这问题:他原本在每个页面都写了Session判断,结果漏了个后台统计页,答辩时老师一试就撞进去了,差点没及格。后来我教他用过滤器搞定,不到半天就堵上所有未登录访问的漏洞,答辩时老师还夸他安全意识强。
为什么过滤器是Servlet+JSP防未登录的“最优解”?
我之前也试过在每个JSP页面开头写,但问题太多——漏一个页面就出漏洞,或者有的Servlet忘了加判断(比如处理订单的
OrderServlet
,用户没登录也能发POST请求创建订单)。而过滤器不一样,它是Servlet体系里的“请求守门人”:不管用户访问的是JSP还是Servlet,只要请求路径匹配,都会先经过过滤器的doFilter
方法。就像小区门卫,不管你走大门还是侧门,都要查门禁卡,没卡就不让进。而且过滤器只需要写一次代码,就能全局生效,不用在几十个页面里重复粘贴同样的判断,省时间还不容易错。
Java EE官方文档里也说,Filter的核心作用就是“在请求到达目标资源前预处理请求”(参考Java EE 7官方文档)。防未登录刚好是“预处理请求”的典型场景:过滤器先查Session里有没有登录用户的信息,没有就直接Redirect到登录页,根本不给请求到达目标页面的机会。
手把手教你搭过滤器:3步搞定未登录拦截
我帮学弟做的时候用的是Servlet 3.1版本,步骤特别简单,你跟着做就行——
第一步:写Filter类,核心逻辑就几行
新建一个Java类(比如叫LoginFilter
),继承javax.servlet.http.HttpFilter
(比直接实现Filter
接口方便,不用强转request
和response
),重写doFilter
方法:
public class LoginFilter extends HttpFilter {
@Override
protected void doFilter(HttpServletRequest req, HttpServletResponse resp, FilterChain chain) throws IOException, ServletException {
//
拿Session,判断有没有登录用户
HttpSession session = req.getSession();
Object loginUser = session.getAttribute("loginUser"); // 登录时存的key要一致!
//
获取请求URI,判断要不要放行(比如登录页、静态资源)
String uri = req.getRequestURI();
if (uri.contains("/login.jsp") // 放行登录页
|| uri.contains("/loginServlet") // 放行登录接口
|| uri.contains("/css/") // 放行CSS
|| uri.contains("/js/")) { // 放行JS
chain.doFilter(req, resp); // 直接放行
return;
}
//
没登录?跳转登录页;登录了?继续请求
if (loginUser == null) {
resp.sendRedirect(req.getContextPath() + "/login.jsp"); // 跳登录页
return;
}
chain.doFilter(req, resp); // 登录了,让请求过去
}
}
这里要注意3个坑——
login.jsp
都拦截,用户根本没法登录,会陷入“点击登录→跳转登录页”的死循环; /css/
和/js/
的判断才好); session.setAttribute("loginUser", user)
,过滤器里就要判断loginUser
,别写错成user
或者username
,不然永远拦截。第二步:配置过滤器,两种方式任选
过滤器要“生效”,得告诉Servlet容器“哪些请求要经过这个过滤器”。有两种配置方式,看你项目版本选:
配置方式 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
@WebFilter注解 | 代码简洁,不用改XML | 需要Servlet 3.0+ | 新项目、快速开发 |
web.xml配置 | 兼容性好(支持所有版本) | 要手动写XML,略繁琐 | 老旧项目、需要精确配置 |
用注解的话,直接在LoginFilter
类上加一行:
@WebFilter(urlPatterns = {"/user/", "/backend/"}) // 只拦截需要登录的路径
public class LoginFilter extends HttpFilter { ... }
用web.xml的话,在web.xml
里加:
LoginFilter
com.example.filter.LoginFilter
LoginFilter
/user/ <!-
拦截用户中心路径 >
/backend/ <!-
拦截后台路径 >
这里要注意urlPattern别设成/
!我朋友做电商后台时就犯过这错:设成/
后,所有请求都被拦截,包括登录页,用户点登录按钮就跳回登录页,后来改成/backend/
只拦截后台页面,问题才解决。
第三步:测试效果,确认漏洞被堵死
启动项目,先不登录,直接输http://localhost:8080/user/center.jsp
——如果自动跳转到login.jsp
,说明过滤器生效了;登录之后再访问,能正常进个人中心,就对了。
我学弟测试时发现,之前漏的那个统计页http://localhost:8080/backend/stat.jsp
果然被拦截了,他高兴得跟我说:“终于不用怕老师再挑刺了!”
最后再跟你说个小技巧:要是想加角色控制(比如普通用户不能进后台,管理员能进),其实就是在过滤器里加个角色判断。比如登录时存session.setAttribute("role", "admin")
,过滤器里加一行:
if ("admin".equals(session.getAttribute("role"))) {
chain.doFilter(req, resp); // 管理员放行
} else {
resp.sendRedirect(req.getContextPath() + "/user/center.jsp"); // 普通用户跳个人中心
}
我学弟后来加了这功能,答辩时老师问他怎么区分管理员和普通用户,他一演示,老师直接给了优。
你要是按这些步骤试了,说不定会发现之前的项目安全多了。其实过滤器不止能防未登录,还能做日志记录(比如记录每个请求的IP和时间)、字符编码过滤(统一处理中文乱码)——我之前做的一个项目,用过滤器统一设置request.setCharacterEncoding("UTF-8")
,比在每个Servlet里写方便10倍。
要是你试的时候碰到问题——比如过滤器不生效、静态资源被拦截,欢迎在评论区留言,我帮你看看!
过滤器和在每个页面写Session判断有什么区别?
之前我学弟在每个JSP页面开头写Session判断,结果漏了后台统计页,答辩时被老师发现漏洞。而过滤器是全局的,只要写一次代码,所有匹配的请求都会先经过它查身份,不用在几十个页面重复粘贴同样的判断,省时间还不容易漏。比如你有10个需要登录的页面,用过滤器只要配置一次,比每个页面写判断靠谱多了。
过滤器会不会把登录页也拦截了?
肯定会啊,我之前就犯过这错——把login.jsp也加进拦截规则里,结果用户点登录按钮就跳回登录页,陷入死循环。所以一定要在过滤器里配置“放行清单”:比如登录页(login.jsp)、处理登录的Servlet(loginServlet),还有CSS/JS这些静态资源,不然用户没法登录,页面还会乱码。
过滤器配置好后不生效怎么办?
先检查urlPattern是不是写错了,比如你本来想拦截后台路径,结果写成/,把所有请求都拦了,包括登录页,肯定不对。再看看Filter类有没有加@WebFilter注解(Servlet3.0+可用),或者web.xml里有没有配置filter-mapping——要是没告诉容器“这个过滤器管哪些路径”,它根本不会工作。我学弟之前就是漏了web.xml的配置,后来加上就好了。
过滤器能区分管理员和普通用户吗?
当然能!比如你登录时往Session里存个role字段:普通用户存“user”,管理员存“admin”。然后在过滤器里加段判断——如果Session里的role是“admin”,就放行后台路径(比如/backend/*);如果是“user”,就跳转到个人中心页面。我学弟后来加了这功能,答辩时老师问他怎么区分权限,他一演示,老师直接给了优。
静态资源(比如CSS、JS)被过滤器拦截了怎么办?
这是常见坑!比如你没给CSS路径放行,页面加载时过滤器会拦截CSS请求,导致页面没样式,像裸奔的文字。解决办法很简单——在过滤器的放行规则里加进静态资源的路径,比如/css/、/js/,这样过滤器就不会拦这些文件了。我之前帮朋友调项目时,就是漏了放行JS路径,结果按钮点不动,加上就好了。