Tomcat使用过滤器实现页面的限制访问
需要解决的问题
最近在学tomcat,当接触到过滤器时,想着怎样才能对所有的页面请求都进行一次拦截筛选,实现只放行登录页面,如果访问其他页面,则必须登录,如果没有登录,则跳转到登录页面。这是为了防止没有登录的用户通过url非法访问网站的其他受限页面,使用过滤器来对网站的所有页面都设置访问限制,避免了用户通过url跳过登录环节而访问到受限制的页面资源。
在学习过程中,学到了在web.xml中一个一个配置的方法,但是如果按照那种一个一个页面添加的方法,如果页面较少还行,但是当页面多达几十个以上,这种方法未免太过麻烦。在网上查找后,找到了解决办法,在此做记录,方便查看。
单独添加的方法:
<filter>
<filter-name>QualFilter</filter-name>
<filter-class>com.tomcat.filter.QualFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>QualFilter</filter-name>
<url-pattern>/index.jsp</url-pattern>
<url-pattern>/welcome.jsp</url-pattern>
<url-pattern>/home.jsp</url-pattern>
......等等
</filter-mapping>
</filter-mapping>
</filter-mapping>
在上面的方法中,我将index.jsp、welcome.jsp、home.jsp等加入了过滤器 处理的名单中,使每次发送这些页面的请求过来时都会被过滤器拦截过滤,使得非法用户无法访问这些页面,但可以看出,当页面增多时,这种方法会让web.xml变得非常臃肿,因此我们需要找到一种更加简洁高效的方法。
更加高效的方法如下:
<filter>
<filter-name>QualFilter</filter-name>
<filter-class>com.tomcat.filter.QualFilter</filter-class>
<init-param>
<param-name>FreePage</param-name>
<param-value>/index.jsp,/login</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>QualFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在web.xml中,“/*”规定了所有的页面请求都将经过滤器的处理,使得我们不用再将所有页面一个一个添加上去,而 /index.jsp,/login设置了一个允许任何用户都可以访问的页面,无论他是否登录,也就是我们的登录页面。index.jsp是我的登录页面,/login是我处理登录页面请求的Servlet,如下:
@WebServlet("/login")
public class LoginServlet extends HttpServlet{
刚刚接触过滤器的人可能对放行的设置部分有所疑问,为什么包含/index.jsp和/login,明明放行登录页面index.jsp就行了,为什么连Servlet中的/login都要放行。
因为我的index.jsp登录页面在输入账号和密码后会转交给Servlet处理,如果不将/login放行, 用户虽然可以到达登录页面,但是当他点击登录时,Servlet无法对这次登录请求作出处理,因为Servlet不在放行名单中,这次请求会被过滤器拦截,而我的Session也还没记录到用户登录的状态(Servlet都无法处理登录请求了,Session怎么能拿到登录状态),那么无论我们提交多少次登录请求,我们还是无法登录成功(一直被限制在登录页面)。
在Filter中实现我们的拦截功能
public class QualFilter implements Filter{
private String FreePages;
private String[] FreePageArray;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
FreePages = filterConfig.getInitParameter("FreePage"); //得到web.xml中设置的免过滤名单,/index.jsp和/login
FreePageArray = FreePages.split(","); // 按照“,”将它们分割,并存入数组
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
boolean isFreePage = false;
arg0.setCharacterEncoding("UTF-8"); // 防止中文乱码
for (String page : FreePageArray) { // 遍历免过滤数组
if(((HttpServletRequest) arg0).getServletPath().equals(page)){
isFreePage = true;
break; // 这次请求的url在免过滤组中,停止遍历
}
}
if (isFreePage) { // 这次请求是免过滤中的url,放行
arg2.doFilter(arg0, arg1);
} else { // 判断用户是否已经登录
HttpServletRequest req = (HttpServletRequest)arg0;
HttpServletResponse resp = (HttpServletResponse)arg1;
HttpSession Session = req.getSession();
String name = (String)Session.getAttribute("name");
if(name != null) { // 检查session中是否保存有记录
arg2.doFilter(arg0, arg1);
}else {
resp.sendRedirect("/index.jsp"); // 不是免过滤名单中的url,且session中无记录,跳转到登录界面
}
}
}
}
}
在public void init(FilterConfig filterConfig)中获取我们Web.xml中设置的免过滤名单,并将其分割到FreePageArray数组中。在doFilter中,我们实现具体的代码,在for()中遍历免过滤数组,与每次过来的请求对比,看过来的请求url是否在免过滤名单中,如果在,则isFreePage = true。
在判断环节,如果过来的请求在免过滤名单中,直接放行,如果不在,检查Session,看这次请求是否为登录用户发过来的,如果是,则放行,如果不是,跳转到登录页面,防止非法的用户通过url绕过登录环节访问受限制页面的资源。
当用户登录时,请求发送到Servlet,如果登陆成功,Session
保存用户的登录状态。当登录用户访问受限页面时,Filter会判断是否放行,当过滤器查看Session`时,发现是已经登录的用户在访问受限页面,则会放行。
在实现了将所有页面都拦截的目的后,出现了登录页面的图片
和css
等资源无法加载的问题,解决办法可以参考另一篇文章:
解决办法:
https://blog.csdn.net/Nebula_DIX/article/details/105031581
参考于: https://www.cnblogs.com/hubing/p/6142072.html.
感谢