基于的过滤器的登录验证

问题背景

目前系统使用的基于拦截器Interceptor的登录验证似乎出了些问题,有些情况下在Controller层获取session中的用户数据时失败。具体原因没有找到,组长说应该是Interceptor这块出了些问题,于是打算将登录验证放到Filter上去做。


基本业务逻辑

1 判断请求url是否需要进行登录验证;

2 如果需要登录验证,则判断是否有登录的用户数据,否则执行过滤器链中的下一个过滤器;

3 如果用户未登录,转跳到登陆页;否则执行过滤器链中的下一个过滤器


堆代码

package com.shtd.common.filter;

import java.io.IOException;
import java.util.regex.Pattern;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import com.shtd.common.util.LoginConstants;
import com.shtd.modules.edu.roll.entity.vo.StuUser;

public class LoginFilter extends OncePerRequestFilter{

	private String excludedPages;       
	private String[] excludedPageArray;   
	
	@Override
	protected void doFilterInternal(HttpServletRequest request,
			HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {
//		System.out.println(" ==登录过滤==" + request.getServletPath());
		HttpSession session = request.getSession();
		StuUser curUser = (StuUser)session.getAttribute(LoginConstants.SESSION_KEY_CURUSER);
		if  (curUser == null || curUser.getId() ==  null){
//			System.out.println(" ==未通过==");
			response.sendRedirect(request.getContextPath()+ "/login");
		} else {
//			System.out.println(" ==通过==");
			filterChain.doFilter(request, response);
		}
	}
	
	/**
	 * 初始化时获得参数
	 */
	@Override
	protected void initFilterBean() throws ServletException {
//		System.out.println("初始化 登录过滤器");
		excludedPages = getFilterConfig().getInitParameter("exclusions"); 
		if (StringUtils.isNotEmpty(excludedPages)) {     
			excludedPageArray = excludedPages.split(",");
			for (int i=0; i < excludedPageArray.length; i++) {
				String excludedPage = excludedPageArray[i];
				if (excludedPage.contains("**")){
					StringBuilder builder = new StringBuilder();
					builder.append("^");
					builder.append(StringUtils.replace(excludedPage, "**", "\\S*"));
					builder.append("$");
					excludedPageArray[i] = builder.toString();
				}
//				System.out.println(excludedPageArray[i]);
			}
		}
	}
	
	/**
	 * 是否要跳过过滤器
	 */
	protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
		if (excludedPageArray == null || excludedPageArray.length == 0) {
			return false;
		}
		String path = request.getServletPath();
		for (String excludedPage : excludedPageArray) {
			if (StringUtils.isBlank(excludedPage)) {
				continue;
			}
			if (excludedPage.startsWith("^")){
				if (Pattern.matches(excludedPage, path)) {
					return true;
				}
			} else if (excludedPage.equals(path)) {
				return true;
			}
		}
		return false;
	}

}

配置文件

<!-- 登录状态过滤 -->
            <filter>
                        <filter-name>loginFilter</filter-name>
                        <filter-class>com.shtd.common.filter.LoginFilter</filter-class>
                        <init-param>
                                    <param-name>exclusions</param-name>
                                    <param-value>/login,/init-pwd,/authenticate,/resources/**</param-value>
                        </init-param>
            </filter>

            <filter-mapping>
                        <filter-name>loginFilter</filter-name>
                        <url-pattern>/*</url-pattern>
            </filter-mapping>
            <!-- 登录状态过滤, 结束-->


值得注意的点

1 Filter没有类似于Interceptor的exclude-mapping的设置——严重觉得可能是我没找到——只能通过init-param来传入要忽略的路径;

2 一般情况下,实现javax.servlet.Filter就行了,然后我发现继承spring的OncePerRequestFilter会更方便一些。它将init和destroy方法都封装好了,我们只需要关注于doFilter这块。同时也提供和获得传入参数和是否需要进入过滤器的判断方法,只要重写相应的方法就行了

3 记得通过过滤后,执行filterChain.doFilter(request, response);


参考链接

Spring web过滤器-各种filter讲解

Spring Mvc那点事---(19)Spring Mvc过滤器Filter实现登陆验证

猜你喜欢

转载自blog.csdn.net/ranweizheng/article/details/79884570
今日推荐