需求:在项目开发中,按照正常的思路:用户必须登录了才能进入到后台,如果知道后台的地址而直接访问后台,那么该项目可以说是非常的差劲了。由于开发需要,我这几天学习和解决了这个问题。现在分享出现,希望能给大家带来帮助!(在前人的基础上实践!!)
1、写SessionFilter (自定义)过滤器,要实现Filter接口
import java.io.IOException; import java.util.regex.Pattern; import java.net.URLEncoder; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; public class SessionFilter implements Filter{ /**要检查的 session 的名称 */ private String sessionKey; /**需要排除(不拦截)的URL的正则表达式 */ private Pattern excepUrlPattern; /**检查不通过时,转发的URL */ private String forwardUrl; public void init(FilterConfig cfg) throws ServletException{ System.out.println("SessionFilter的启动"); sessionKey= cfg.getInitParameter("sessionKey"); String excepUrlRegex = cfg.getInitParameter("excepUrlRegex"); if (!StringUtils.isBlank(excepUrlRegex)){ excepUrlPattern= Pattern.compile(excepUrlRegex); } forwardUrl= cfg.getInitParameter("forwardUrl"); } public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { System.out.println("执行SessionFilter过滤"); //如果 sessionKey 为空,则直接放行(个人觉得在此这个判断条件没有用) if (StringUtils.isBlank(sessionKey)){ chain.doFilter(req,res); return; } /* 请求 http://127.0.0.1:8080/sm/index.jsp?&a=1&b=2 时 * request.getRequestURL(): http://127.0.0.1:8080/sm/index.jsp * request.getContextPath(): /sm * request.getServletPath():/index.jsp * request.getRequestURI(): /sm/index.jsp * request.getQueryString():a=1&b=2 */ HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; String servletPath = request.getServletPath(); System.out.println("servletPath="+servletPath); //如果请求的路径与forwardUrl相同,或请求的路径是排除的URL时,则直接放行 if (servletPath.equals(forwardUrl)|| excepUrlPattern.matcher(servletPath).matches()) { chain.doFilter(req,res); return; } //注意:adminName为用户登录名,必须在登录信息传到后台时放到Session //里,我的项目在@Controller的登录用户传到后台时当判断用户名和密码正确 //后立马到Session里,作用是用来判断Session如果还有效,返回不为空,可以在后台继续操作;如果超时了,返回null,则跳到登录页面 Object sessionObj = request.getSession().getAttribute("adminName"); //如果Session为空,则跳转到指定页面 if (sessionObj== null){ String contextPath = request.getContextPath(); String redirect = servletPath + "?" +StringUtils.defaultString(request.getQueryString()); response.sendRedirect(contextPath+ StringUtils.defaultIfEmpty(forwardUrl, "/") +"?redirect=" +URLEncoder.encode(redirect, "UTF-8")); }else { //如果能通过,就放行 chain.doFilter(req,res); } } public void destroy(){ System.out.println("SessionFilter的销毁"); } }
文字有一处要注意:即
Object sessionObj = request.getSession().getAttribute("adminName");
中的“adminName”要在后台有设置,否则不起作用,比如我在Controller中这样设置
2、在web.xml中配置如下过滤器信息(重点在如何设置哪些路径需要拦截,哪些不需要拦截)
<!-- 检查用户是否登录了系统的过滤器配置 开始 --> <filter> <filter-name>SessionFilter</filter-name> <filter-class>com.py.util.wrb.SessionFilter</filter-class> <init-param> <description> 将当前登录的用户的信息保存在session 中时使用的key,如果没有配置此参数,则该过滤器不起作用 </description> <param-name>sessionKey</param-name> <param-value>adminName</param-value> </init-param> <init-param> <description> 如果用户未登录(即在session 中 key 为 sessionKey 的属性不存在或为空),则将请求重定向到该 url。 该url 不包含web应用的 ContextPath。如果不配置此参数,则在用户未登录系统的情况下, 直接重定向到web应用的根路径(/) </description> <param-name>forwardUrl</param-name> <param-value>/index.jsp</param-value> </init-param> <init-param> <description> 不需要进行拦截的url 的正则表达式,即:如果当前请求的 url 的 servletPath 能匹配该正则表达式,则直接放行(即使未登录系统)。 此参数的值一般为loginServlet 和 registServlet 等。另外,参数redirectUrl 的值不用包含在该正则表达式中,因为 redirectUrl 对应的 url 会被自动放行。 还有一点需要说明的是,该参数的值不包含web应用的ContextPath。 </description> <param-name>excepUrlRegex</param-name> <!-- 不需要拦截的路径 (login_login_execute|login_2_login).do 会在后面有详细的解释 --> <param-value>/(jumpIndex|loginAdmin)</param-value> </init-param> </filter> <!-- /* 表示所有的都要进行过滤--> <filter-mapping> <filter-name>SessionFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
耐心讲解:打个比方,如果你登录你的系统要输入这样的地址进入登录界面:
http://127.0.0.1:8080/sm/index.jsp
那么forwardUrl应该是这样写,代表页面的登录页面(forwardUrl可自定义名称,当然要见词知意最好,下同)
<param-name>forwardUrl</param-name> <param-value>/index.jsp</param-value>
在一个系统中,我们一般把登录页面放在web-inf的外面,否则直接访问不了(个人见解),为了起到保护作用,我们在登录页面点击登录,要做一些路径跳转,有多个跳转就有多少个路径,直到后台的主界面,这些路径也必须不能拦截,否则你登录不到后台。如下,这里说明登录到后台要经过jumpIndex和loginAdmin路径,“|”代表“或”
<description> 不需要进行拦截的url 的正则表达式,即:如果当前请求的 url 的 servletPath 能匹配该正 则表达式,则直接放行(即使未登录系统)。 此参数的值一般为loginServlet 和 registServlet 等。另外,参数redirectUrl 的值不用 包含在该正则表达式中,因为 redirectUrl 对应的 url 会被自动放行。 还有一点需要说明的是,该参数的值不包含web应用的ContextPath。 </description> <param-name>excepUrlRegex</param-name> <param-value>/(jumpIndex|loginAdmin)</param-value>
3、为了方便测试,最好设置Session的有效时间短一点,如何设置Session有效时间百度有一大堆,我是在web.xml重配置的,如:我设置有效时间为1分钟
<session-config> <session-timeout>1</session-timeout> </session-config>
这样可以在Session失效后直接登录后台看是否进得去
比如我登录后台后的一个路径为:http://127.0.0.1:8080/sm/camera
当Session失效后在新的地址栏上输入:http://127.0.0.1:8080/sm/camera
看是否能进入。进不去,说明过滤器起作用了。
至此完成,有什么问题可以留言,我会及时回复!后面我会继续完善这篇文章,希望各位能给点指点,谢谢!
声明:我通过百度上找很多资料,结合自己项目做的,我希望能对大家有所帮助。