SpringMVC使用过滤器处理登陆跳转问题

问题描述:

        如果一个页面的功能需要登陆后才能使用,比如用户的个人中心,此时,点到个人中心,系统判断用户是否登陆,如果没有登陆,则跳转到登陆页面,登陆完后自动跳转到个人中心,如果用户已经登陆了,则直接跳转到个人中心。

思路:

      使用过滤器对请求进行过滤,判断session中是否有用户,如果有用户则直接放行,如果session中没有用户,判断请求是否是需要过滤的请求,如果是不是需要过滤的请求则放行,如果是需要过滤的请求,则进行过滤。在请求中把目标url作为变量放在请求中,在第二次请求中即可跳转到该页面。

实现:

       本人表达能力有限,如果看不懂描述的话可以看代码,首先是在web.xml中进行配置过滤器

<!-- Session 过滤器 -->
<!-- 检查用户是否登录了系统的过滤器配置  开始 -->
<filter>
    <filter-name>SessionFilter</filter-name>
    <filter-class>cn.xaut.filter.SessionFilter</filter-class>
    <init-param>
        <description>将当前登录的用户的信息保存在 session 中时使用的key,如果没有配置此参数,则该过滤器不起作用</description>
        <param-name>sessionKey</param-name>
        <param-value>user</param-value>
    </init-param>
    <init-param>
        <description>
	    如果用户未登录(即在 session 中 key 为 sessionKey 的属性不存在或为空),则将请求重定向到该 url。
	    该 url 不包含web应用的 ContextPath。
	    如果不配置此参数,则在用户未登录系统的情况下,直接重定向到web应用的根路径(/)
        </description>
        <param-name>forwardUrl</param-name>
        <param-value>/toLogin</param-value>
    </init-param>
    <init-param>
        <description>
	    不需要进行拦截的 url 的正则表达式,即:如果当前请求的 url 的 servletPath 能匹配该正则表达式,则直接放行(即使未登录系统)。
	    此参数的值一般为 loginServlet 和 registServlet 等。
	    另外,参数 redirectUrl 的值不用包含在该正则表达式中,因为 redirectUrl 对应的 url 会被自动放行。
	    还有一点需要说明的是,该参数的值不包含web应用的 ContextPath。
	    不拦截 /servlets/loginServlet 和 /servlets/registServlet 
        </description>
        <param-name>excepUrlRegex</param-name>
        <param-value>toLogin|toRegist</param-value>
    </init-param>
    <init-param>
        <description>首页地址</description>
	<param-name>indexPage</param-name>
	<param-value>userActioin_goPortals.do</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>SessionFilter</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>

接下来新建一个SessionFilter.java类,该类实现Filter接口,所以要重写init(),doFilter(),destroy()三个方法

package cn.xaut.filter;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.Enumeration;
import java.util.regex.Pattern;
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 {
/**
* 用于检查用户是否登录了系统的过滤器<br>
* @author wft
*/

//自定义Session超时状态为 timeout
public static final String Session_Time_Out = "timeout";
/** 自定义response状态值**/
public static final int ReponseState = 911; 

/** 要检查的 session 的名称 */
private String sessionKey;

/** 需要排除(不拦截)的URL的正则表达式 */
private Pattern excepUrlPattern;

/** 检查不通过时,转发的URL */
private String forwardUrl;

/** 网站首页地址 */
private String indexPage;

@Override
public void init(FilterConfig cfg) throws ServletException {
sessionKey = cfg.getInitParameter("sessionKey");
indexPage = cfg.getInitParameter("indexPage");

String excepUrlRegex = cfg.getInitParameter("excepUrlRegex");

if (!StringUtils.isBlank(excepUrlRegex)) {
excepUrlPattern = Pattern.compile(excepUrlRegex);
}

forwardUrl = cfg.getInitParameter("forwardUrl");
}

@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {

// 如果 sessionKey 为空,则直接放行
if (StringUtils.isBlank(sessionKey)) {
chain.doFilter(req, res);
return;
}

HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;

// 要请求的地址
String servletPath = request.getServletPath();
// 工程项目地址
String contextPath = request.getContextPath(); 

Object sessionObj = request.getSession().getAttribute(sessionKey);

if(sessionObj == null && servletPath.equals("/")){
chain.doFilter(req, res);
return;
}
	        //对静态资源进行处理
		if (servletPath.endsWith(".css") || servletPath.endsWith(".js") 
                || servletPath.endsWith(".png") || servletPath.endsWith(".jpg")||servletPath.endsWith(".jpeg")
                || servletPath.endsWith(".gif") || servletPath.endsWith(".jsp")||servletPath.endsWith("/GoSport/")
                || servletPath.endsWith(".html")) {
			chain.doFilter(req, res);
			return;
        }
		// 如果请求的路径与forwardUrl相同,或请求的路径是排除的URL时,则直接放行
		if (sessionObj !=null || servletPath.equals(forwardUrl)|| excepUrlPattern.matcher(servletPath).matches()) {
			chain.doFilter(req, res);
			return;
		}

		
		// 如果Session为空,则跳转到指定页面
		if (sessionObj == null) {
			
			System.out.println("Session Filter Catched");
			System.out.println("ServletPath -> " + servletPath);
			
			//登录后返回的页面
			String redirect = "";
			
			//判断发起请求的类型 : http 或者 ajax
			String type = request.getHeader("X-Requested-With");  
			
			if ("XMLHttpRequest".equalsIgnoreCase(type)) {
				System.out.println("Ajax 请求");
                                redirect = request.getHeader("referer");
                                if(redirect == null)
                	        redirect = contextPath + indexPage;
                        //获取到的url进行截取,等号后面的内容为目标url
                if(redirect.indexOf("=")!=-1){
                      String url[] = redirect.split("=");
                    String goUrl = url[1];
                    request.getSession().setAttribute("goUrl",goUrl);
                }
			chain.doFilter(req, res);
                return;
            } else {
            	// NORMAL REQUEST PROCESS
            	System.out.println("Http 请求");
            	redirect = getHttpGoUrl(request);
            } 
			
			
			System.out.println("redirect --> " + redirect);
			
			// 抓住后要前往的地址
			String forword = StringUtils.defaultIfEmpty(forwardUrl, "/");
			
			// 编码重定向地址
			redirect = URLEncoder.encode(redirect,"UTF-8");
			request.getSession().setAttribute("goUrl",redirect);
			
			System.out.println("跳回登录页");
			response.sendRedirect(contextPath + forword+ "?redirect=" +redirect);
			/*response.sendRedirect(contextPath + forword);*/
		}
	}
	
	/**
	 * http请求action,直接跳去这个action
	 * */
	private String getHttpGoUrl(HttpServletRequest request){
		
		StringBuffer buffer = new StringBuffer();
		String url = request.getServletPath();
		buffer.append(url);
		
		String param = request.getQueryString();//获取get的请求参数
		Enumeration<String> emParams = request.getParameterNames();//获取post的请求参数
		if (param != null) {
			buffer.append("?");
			buffer.append(param);
		}
		else
		{
			//post提交参数
			boolean first = true;
			do {
				if (!emParams.hasMoreElements()) {
					break;
				}
				String sParam = (String) emParams.nextElement();
				String[] sValues = request.getParameterValues(sParam);

				String sValue = "";
				for (int i = 0; i < sValues.length; i++) {
					sValue = sValues[i];
					//if (sValue != null && sValue.trim().length() != 0 && first == true)
					if (sValue != null && first == true) {
						// 第一个参数
						first = false;
						buffer.append("?");
						buffer.append(sParam).append("=").append(sValue);
								
					//} else if (sValue != null && sValue.trim().length() != 0 && first == false) {
					} else if (sValue != null && first == false) {
						buffer.append("&").append(sParam).append("=").append(sValue);
					}
				}
			} while (true);
		}
		return buffer.toString();
		
	}
	

	@Override
	public void destroy() {
	}
}

过滤器添加完了之后还需要在LoginController中添加重定向的代码

if (session.getAttribute("goUrl") != null)
	//如果需要重定向
    {
        goUrl = URLDecoder.decode(session.getAttribute("goUrl").toString(),"UTF-8");
        session.removeAttribute("goUrl");// 这里移除掉,免得又跳转
        errorInfo = goUrl;
    }

因为我的登陆是用ajax方式提交的,所以在ajax的代码中也需要添加跳转的代码

success : function(json) {
    if(json.result == 'error'){
        alert('用户名或密码错误!');
        return;
    }else if(json.result == 'validateFalse'){
    	alert('验证码错误!');
    	return;
    }else if(json.result == 'success'){
 	window.location.href=getRootPath();
    	return;
    }else{
        //跳转到目标url
    	window.location.href= getRootPath()+json.result;
    	return;
    }
},

至此登陆过滤器就算完成了,要过滤的action只需要在web.xml中的excepUrlRegex中添加即可

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值