需求:在项目开发中,按照正常的思路:用户必须登录了才能进入到后台,如何知道后台的地址而直接访问后台,那么该项目可以说是非常的差劲了。由于开发需要,我这几天学习和解决了这个问题。现在分享出现,希望能给大家带来帮助!
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");
System.out.println("sessionObj="+sessionObj);
//如果Session为空,则跳转到指定页面
if (sessionObj== null){
String contextPath = request.getContextPath();
String redirect = servletPath + "?" +StringUtils.defaultString(request.getQueryString());
System.out.println("contextPath="+contextPath+",redirect="+redirect);
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
看是否能进入。进不去,说明过滤器起作用了。
至此完成,有什么问题可以留言,我会及时回复!后面我会继续完善这篇文章,希望各位能给点指点,谢谢!
声明:我通过百度上找很多资料,结合自己项目做的,我希望能对很多菜鸟有所帮助。