码迷,mamicode.com
首页 > 编程语言 > 详细

springmvc的HandlerInterceptor的简单了解(登录例子)

时间:2017-12-06 18:11:01      阅读:233      评论:0      收藏:0      [点我收藏+]

标签:java   springmvc   interceptor   cookie   登录   

  • 抽象的类

  • package com.book.admin.interceptor;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.regex.Pattern;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    /**
     * 
     * @author liweihan
     *
     */
    public abstract class AbstractInterceptor implements HandlerInterceptor{
    	
    	private static Logger logger = LoggerFactory.getLogger(AbstractInterceptor.class);
    	
    	//不需要拦截的链接
    	protected static List<String> excludeActionList = new ArrayList<String>();
    	
    	static {
            excludeActionList.add("^/(login|static)(/)?(.+)?$");
            excludeActionList.add("^/(flush|test|site_map)(/)?(.+)?$");     //redis data flush
            excludeActionList.add("^/app/(flush|info.json|apkinfo.json)(/)?(.+)?$");    //前端接口http://m.tv.sohu.com/app
            excludeActionList.add("^/(hikeapp)(/)?(.+)?$");        //需要拉起客户端的专辑数据访问接口
            excludeActionList.add("^/(cooperation|activity|api|open|mobile|mb)(/)?(.+)?$");
            excludeActionList.add("^/(activity|api|open|mobile|mb)(/)?(.+)?$");
            excludeActionList.add("^/(test)(/)?(.+)?$");
    	}
    
    	public boolean preHandle(HttpServletRequest request,
    			HttpServletResponse response, Object handler) throws Exception {
    //		logger.debug(" ====== prehandle !");
    //		logger.info(" ======= URI:{}",request.getRequestURI());
    		request.setAttribute("uri", request.getRequestURI());//为了突出显示选中的链接
    		for(String excludeUrl : excludeActionList) {
    			if(Pattern.matches(excludeUrl, request.getRequestURI())) {
    				return true;
    			}
    		}
    		return innerPreHandle(request, response, handler);
    	}
    	
    	protected abstract boolean innerPreHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
    
    	public void postHandle(HttpServletRequest request,
    			HttpServletResponse response, Object handler,
    			ModelAndView modelAndView) throws Exception {
    //		logger.debug(" ====== postHandle !");
    	}
    
    	public void afterCompletion(HttpServletRequest request,
    			HttpServletResponse response, Object handler, Exception ex)
    			throws Exception {
    //		logger.debug(" ====== afterCompletion !");
    	}
    }


       2.权限过滤

    package com.book.admin.interceptor;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.regex.Pattern;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.commons.lang.StringUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.util.WebUtils;
    
    import com.book.core.model.AdminFunctions;
    import com.book.core.model.AdminRight;
    import com.book.core.model.User;
    import com.book.core.service.AdminFunctionsService;
    import com.book.core.service.AdminRightService;
    import com.book.core.utils.Constants;
    
    /**
     * 用户权限过滤
     * @author liweihan
     *
     */
    public class FunctionsInterceptor extends AbstractInterceptor{
    	
    	private static Logger logger = LoggerFactory.getLogger(FunctionsInterceptor.class);
    	
    	@Autowired
    	private AdminRightService adminRightService;
    	@Autowired
    	private AdminFunctionsService adminFunctionsService;
    	
    	//登录后不需要拦截的链接
    	protected static List<String> excludeActionList = new ArrayList<String>();
    	
    	static {
            excludeActionList.add("^/(index|admin/user|admin/myinfo)(/)?(.+)?$");
            excludeActionList.add("^/(book/del|book/detail.json|book/addorupdate)(/)?(.+)?$");
    	}
    
    	@Override
    	protected boolean innerPreHandle(HttpServletRequest request,
    			HttpServletResponse response, Object handler) throws Exception {
    		try {
    			User user = (User) WebUtils.getSessionAttribute(request, Constants.ADMIN_SESSION_USER_KEY);
    			if (user == null) {
    				response.sendRedirect("/login");
    				return false;
    			}
    			
    			//查找该用户的权限
    			AdminRight adminRight = adminRightService.getObjByUserName(user.getName());
    			if (adminRight == null) {
    				return true;
    			}
    			
    			List<AdminFunctions> menus = null;
    			if (adminRight.getIsAdmin() == 1) {
    				menus = adminFunctionsService.getAll(); 
    				
    				request.setAttribute("menus", menus);
    				request.setAttribute("isAdmin", adminRight.getIsAdmin());
    				return true;
    			} else {
    				String right = adminRight.getRights();
    				if (StringUtils.isNotBlank(right)) {
    					String[] rs = right.split(",");
    					List<Integer> listId = null;
    					
    					if (rs != null && rs.length > 0) {
    						listId = new ArrayList<Integer>();
    						for (int i = 0; i < rs.length; i++) {
    							if (StringUtils.isNotBlank(rs[i])) {
    								listId.add(Integer.valueOf(rs[i]));
    							}
    						}
    					}
    					
    					//查询
    					menus = adminFunctionsService.getObjByIds(listId);
    				}
    				for(String excludeUrl : excludeActionList) {
    					if(Pattern.matches(excludeUrl, request.getRequestURI())) {
    						request.setAttribute("menus", menus);
    						request.setAttribute("isAdmin", adminRight.getIsAdmin());
    						return true;
    					}
    				}
    				//对权限进行过滤,不能输入URL就可以访问
    				if (menus != null && menus.size() > 0) {
    					for(AdminFunctions adminFunctions : menus) {
    						if (request.getRequestURI().startsWith(adminFunctions.getUrl())) {
    							logger.info(" ====== request.getRequestURI():{},table-url:{}",request.getRequestURI(),adminFunctions.getUrl());
    							request.setAttribute("menus", menus);
    							request.setAttribute("isAdmin", adminRight.getIsAdmin());
    							return true;
    						}
    					}
    				}
    			}
    			response.sendRedirect("/login");
    			return false;
    		} catch (Exception e) {
    			logger.error(" ====== get AdminRight error!",e);
    			e.printStackTrace();
    		}
    		
    		return false;
    	}
    
    }

       3.登录验证

    package com.book.admin.interceptor;
    
    import java.net.URLEncoder;
    import java.util.Calendar;
    import java.util.Date;
    import java.util.UUID;
    
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.util.WebUtils;
    
    import com.book.core.model.PersistentLogins;
    import com.book.core.model.User;
    import com.book.core.service.PersistentLoginsService;
    import com.book.core.service.UserService;
    import com.book.core.utils.Constants;
    import com.book.core.utils.CookieUtil;
    import com.book.core.utils.EncryptionUtil;
    
    
    /**
     * 登录验证拦截器
     * @author liweihan
     *
     */
    public class LoginInterceptor extends AbstractInterceptor{
    	
    	private static Logger logger = LoggerFactory.getLogger(LoginInterceptor.class);
    	@Autowired
    	private PersistentLoginsService persistentLoginsService;
    	@Autowired
    	private UserService userService;
    
    	@Override
    	protected boolean innerPreHandle(HttpServletRequest request,
    			HttpServletResponse response, Object handler) throws Exception {
    		
    		User user = (User) WebUtils.getSessionAttribute(request, Constants.ADMIN_SESSION_USER_KEY);
    		if (user != null) {
    			//已登录
    			return true;
    		} else {
    			//从cookie中取值
    			Cookie cookie = CookieUtil.getCookie(request, Constants.RememberMe_Admin);
    			if (cookie != null) {
    				String cookieValue = EncryptionUtil.base64Decode(cookie.getValue());
    				String[] cValues = cookieValue.split(":");
    				if (cValues.length == 2) {
    					String userNameByCookie = cValues[0];//获取用户名
    					String uuidByCookie = cValues[1];//获取UUID值
    					
    					//到数据库中查询自动登录记录
    					PersistentLogins pLogins  = persistentLoginsService.getObjByUUID(uuidByCookie);
    					if (pLogins != null) {
    						String savedToken = pLogins.getToken();
    						
    						//获取有效时间
    						Date savedValidTime = pLogins.getValidTime();
    						Date currentTime = new Date();
    						
    						//如果还在有效期内,记录判断是否可以自动登录
    						if (currentTime.before(savedValidTime)) {
    							User u = userService.getUserByName(userNameByCookie);
    							if (u != null) {
    								Calendar calendar = Calendar.getInstance();
    								calendar.setTime(savedValidTime);
    								
    								// 精确到分的时间字符串
    								String timeString = calendar.get(Calendar.YEAR) + "-" + calendar.get(Calendar.MONTH)
    										+ "-" + calendar.get(Calendar.DAY_OF_MONTH) + "-"
    										+ calendar.get(Calendar.HOUR_OF_DAY) + "-" + calendar.get(Calendar.MINUTE);
    								// 为了校验而生成的密文
    								String newToken = EncryptionUtil.sha256Hex(u.getName() + "_" + u.getPassword() + "_"
    										+ timeString + "_" + Constants.salt);
    								
    								// 校验sha256加密的值,如果不一样则表示用户部分信息已被修改,需要重新登录
    								if (savedToken.equals(newToken)) {
    									//为了提高安全性,每次登录之后都更新自动登录的cookie值
    									String uuidNewString = UUID.randomUUID().toString();
    									String newCookieValue = EncryptionUtil.base64Encode(u.getName() + ":" + uuidNewString);
    									CookieUtil.editCookie(request, response, Constants.RememberMe_Admin, newCookieValue, null);
    									
    									//同时更新数据
    									pLogins.setSeries(uuidNewString);
    									pLogins.setUpdateTime(new Date());
    									persistentLoginsService.updateByObj(pLogins);
    									
    									//将用户加到session中,不退出浏览器时只需要判断session即可
    									WebUtils.setSessionAttribute(request, Constants.ADMIN_SESSION_USER_KEY, u);
    									
    									//校验成功,此次拦截操作完成
    									return true;
    								} else {
    									//用户信息部分被修改,删除cookie并清空数据库中的记录
    									CookieUtil.delCookie(response, cookie);
    									persistentLoginsService.delObjById(pLogins.getId());
    								}
    							}
    						} else {
    							// 超过保存的有效期,删除cookie并清空数据库中的记录
    							CookieUtil.delCookie(response, cookie);
    							persistentLoginsService.delObjById(pLogins.getId());
    						}
    					}
    				}
    			}
    			
    			try {
    				response.sendRedirect("/login?src=" + URLEncoder.encode(request.getRequestURI(), "UTF-8"));
    			} catch (Exception e) {
    				logger.error(" ===== loginInterceptor error ,url:{}{}",request.getRequestURL(),request.getRequestURI(),e);
    			} 
    			return false;
    		}
    	}
    
    }

       4.spring-mvc-servlet.xml的配置

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"  
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:mvc="http://www.springframework.org/schema/mvc" 
        xmlns:context="http://www.springframework.org/schema/context" 
        xsi:schemaLocation=" 
            http://www.springframework.org/schema/beans  
            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
            http://www.springframework.org/schema/context  
            http://www.springframework.org/schema/context/spring-context-3.0.xsd 
            http://www.springframework.org/schema/mvc 
            http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
    	
    	<!-- 指定一个包让其自动扫描 -->
    	<context:component-scan base-package="com.book.admin.controller"/>
    
    	<mvc:annotation-driven/>
    	
    	<!-- 下面注释的部分表示:强调所有的请求都要经过springmvc框架 -->
        <mvc:default-servlet-handler/>
    	
    	<!-- 放行了以/static/开始的请求 -->
    	<mvc:resources location="/static/" mapping="/static/**"/> 
    	
    	<!-- 当一个方法完全是为了跳转时,我们可以省略该方法,而在此写一个配置就行了
    	<mvc:view-controller path="/index" view-name="index"/>
    	<mvc:view-controller path="/main" view-name="main"/>
    	<mvc:view-controller path="/success" view-name="success"/> 
    	<mvc:view-controller path="/index" view-name="main"/>
    	<mvc:view-controller path="/" view-name="main"/> 
    	<mvc:view-controller path="/admin/myinfo" view-name="myinfo"/>-->
    	<!-- 
    	<mvc:view-controller path="/book" view-name="book"/>
    	 -->
    	
    	<mvc:interceptors>
    		<bean class="com.book.admin.interceptor.LoginInterceptor"></bean>
    		<bean class="com.book.admin.interceptor.FunctionsInterceptor"></bean>
    		<!--  
    		<mvc:interceptor>  
    	        <mvc:mapping path="/test/number.do"/>  
    	        <bean class="com.host.app.web.interceptor.LoginInterceptor"/>  
    	    </mvc:interceptor>  
    	    -->
    	</mvc:interceptors>
    	
    	<!-- 配置springmvc的视图解析器 -->
    	<bean id="viewResolver" 
    		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    		<property name="suffix" value=".jsp"/>
    		<property name="prefix" value="/WEB-INF/views/"/>
    	</bean>
    	
    	<!-- 文件上传解析器   -->
    	<bean id="multipartResolver" 
    	    class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> 
    	    <property name="maxUploadSize" value="100000"/> 
    	</bean>
    </beans>

    参考:

    拦截器的基础了解

    http://blog.csdn.net/sunp823/article/details/51694662


    拦截器的详细了解

    http://jinnianshilongnian.iteye.com/blog/1670856


    登录例子的思路了解

    http://blog.51cto.com/983836259/1880284


    正则表达式

    http://www.cnblogs.com/sparkbj/articles/6207103.html


    springmvc的拦截器和过滤器的区别

    http://blog.csdn.net/xiaoyaotan_111/article/details/53817918


    java Web中的过滤器Filter和interceptor的理解

    http://www.jianshu.com/p/39c0cfe25997


    springmvc的HandlerInterceptor的简单了解(登录例子)

    标签:java   springmvc   interceptor   cookie   登录   

    原文地址:http://blog.51cto.com/hanchaohan/2047966

    (0)
    (0)
       
    举报
    评论 一句话评论(0
    登录后才能评论!
    © 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
    迷上了代码!