在做登录防止用户没有登录而访问其他web资源的时候,写了一个过滤器,却在浏览器无法打开,出现重定向次数过多 尝试清除cookie,试过没有用。
出现这个问题的原因是因为在过滤器中出现了无限循环重定向。
出现无限循环重定向的原因分析如下:
先上代码:
package net.book.util;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Author: JiangYi
* @Date: 2018/9/18 19:46
* @Description:用来统一设置表单字符集以便对所有请求统一处理表单参数的中文问题;二;不允许
* @Description:未经登录的用户访问站点中的其他任何资源,原理是通过检查session对象中是否保存有用户名来实现
*/
@WebFilter(filterName = "CharacterEncodingFilter",urlPatterns = "/*")
public class CharacterEncodingFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//chain.doFilter(req, resp);
HttpServletResponse response = (HttpServletResponse) resp;
HttpServletRequest request = (HttpServletRequest) req;
request.setCharacterEncoding("utf-8");
//获得基准地址
String basepath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath() + "/";
//获得访问资源的url
String url = request.getRequestURL().toString();
//获得用户名
String userName = (String) request.getSession().getAttribute("employee");
if(userName!=null||url.equals(basepath+"login.jsp")){
chain.doFilter(req,resp);
}
else{
//未经登录的将强制转到登录界面
response.sendRedirect("login.jsp");
}
}
public void init(FilterConfig config) throws ServletException {
}
}
首先要了解doFilter(resquest,response)的意思。
其在有下一个过滤器的时候,就会执行下一个过滤器,如果没有则跳转到相关的页面。
在刚开始访问时,就是没有登录,此时会跳转到指定的页面,而还是没有登录..........,就这样,无限跳转,就在浏览器访问的时候的到上面的结果了。
但是,上面明明就指定了登录界面放行呀?怎么可能会错?原因就是,上面代码的url为/项目名/文件名,而basepath+login.jsp是一个完整的路径,所以即使重定向到了登录界面,但是,其url为:/项目名/login.jsp,肯定和http://localhost:8080/项目名/login.jsp不匹配呀,所以就这样一直重定向了。
我们进行修改,即把
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();//http://localhost:8080
String url= basePath + url;// "http://locatlhost:8080/erp/请求的"
这个时候,的确不会重定向了,但是一点击登录,就还是会跳到登录界面,这个是为什么呢?
我们仔细想一想,登录操作难道只有login.jsp吗?错了!登录之后,我们点击提交,是需要访问相应的servlet的,而由于还没有登录成功,session里面为空,且访问的为登录的servlet,不匹配,所以强制就跳转到登录界面,解决方法就是,加入登录的servlet即可:
更改后的代码:
package com.erp.Utils;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebFilter(filterName = "LoginFilter", urlPatterns = {"/*"})
public class LoginFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws ServletException, IOException {
//获取HttpSession对象,判断是否登陆
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String path=request.getContextPath();// "/erp"
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();//http://localhost:8080
String url = request.getRequestURI().toString();// "/erp/请求的"
String currUrl = basePath + url;// "http://locatlhost:8080/erp/请求的"
//在不为登陆页面时,再进行判断,如果不是登陆页面也没有session则跳转到登录页面,
System.out.println("跳转" + currUrl);
System.out.println(basePath + "/erp/login.jsp");
if (request.getSession().getAttribute("employee") != null || currUrl.equals(basePath + path+"/login.jsp") ||
currUrl.equals(basePath + path+"/loginServlet.do")) {
chain.doFilter(request, response);
return;
} else {
System.out.println("没有登录");
response.sendRedirect("login.jsp");
return;
}
}
public void init(FilterConfig config) throws ServletException {
}
}
这里的重点就是:
currUrl.equals(basePath + path+"/login.jsp")
另外,由于这里使用equals,所以需要url和我们设置的过滤规则里面的完全一样!这就需要我们后续在编写相关的代码中,对于涉及路径的编写要相当的谨慎,比如前一个地址为:
http://localhost:8080/erp//createUser.jsp
而由于跳转,会重定向到:http://localhost:8080/erp//login.jsp,注意看,这里是有两个斜杠,所以与我们的过滤规则里面定义的url不匹配,就又会出现无限重定向的错误!这个要引起我们的重视!
还是SpringMVC里面的拦截器来的省心呀。。。。。