• java无状态登录实现方式之ThreadLocal+Cookie


    注:本文提到的无状态指的是无需session完毕认证、取用户封装信息。

    无状态的优点:

      1。多应用单点登录:在多应用的时候仅仅需在登录server登录后。各子应用无需再次登录。

      2。多server集群:无需制作会话共享的缓存就可以实现。

    此方案的缺点:

      1,依赖于cookie,尽管如今主流浏览器都支持cookie。

      2。单点登录须要各子应用属于同一主域名下(跨主域名无法实现)。

    实现原理:

      登录时封装用户信息,并将用户信息通过序列化加密写到用户cookie。当用户下次请求应用server时,过滤器将用户信息取到反解密反序列化后放入ThreadLocal中,利用ThreadLocal的线程安全特性,之后操作取到用户信息。


    用户封装信息类

    package com.xxx.commons.framework.bean;
    
    import java.io.Serializable;
    
    public class Principal implements Serializable {
    	private static final long serialVersionUID = -1373760761780840081L;
    	
    	private Long id;
    	private String username;
    	private Integer userType;
    	private Long pharmacyId;
    	private Long saleManId;
    	private Long ydId;
    	private String name;
    
    	public Principal(Long id, String username,Integer userType,Long pharmacyId,Long saleManId,Long ydId,String name) {
    		this.id = id;
    		this.username = username;
    		this.userType = userType;
    		this.pharmacyId = pharmacyId;
    		this.saleManId = saleManId;
    		this.ydId = ydId;
    		this.setName(name);
    	}
    
    	public Long getId() {
    		return id;
    	}
    
    	public void setId(Long id) {
    		this.id = id;
    	}
    
    	public String getUsername() {
    		return username;
    	}
    
    	public void setUsername(String username) {
    		this.username = username;
    	}
    
    	@Override
    	public String toString() {
    		return username;
    	}
    
    	public Integer getUserType() {
    		return userType;
    	}
    
    	public void setUserType(Integer userType) {
    		this.userType = userType;
    	}
    
    	/**
    	 * @return pharmacyId
    	 *       
    	 */
    	public Long getPharmacyId() {
    		return pharmacyId;
    	}
    
    	/** 
    	 * @param pharmacyId  
    	 *       
    	 */
    	public void setPharmacyId(Long pharmacyId) {
    		this.pharmacyId = pharmacyId;
    	}
    
    	/**
    	 * @return saleManId
    	 *       
    	 */
    	public Long getSaleManId() {
    		return saleManId;
    	}
    
    	/** 
    	 * @param saleManId  
    	 *       
    	 */
    	public void setSaleManId(Long saleManId) {
    		this.saleManId = saleManId;
    	}
    
    	/**
    	 * @return ydId
    	 *       
    	 */
    	public Long getYdId() {
    		return ydId;
    	}
    
    	/** 
    	 * @param ydId  
    	 *       
    	 */
    	public void setYdId(Long ydId) {
    		this.ydId = ydId;
    	}
    
    	/**
    	 * get name
    	 * @return the name
    	 *       
    	 */
    	public String getName() {
    		return name;
    	}
    
    	/** 
    	 * set name
    	 * @param name  
    	 *       
    	 */
    	public void setName(String name) {
    		this.name = name;
    	}
    	
    }


    用户信息工具类

    /**   
     * Copyright RH Corporation 2014 版权全部  
     * Created 2014年12月18日 下午1:24:27 
     * @version V1.0   
     */
    package com.xxx.commons.framework.utils;
    
    import com.xxx.commons.framework.bean.Principal;
    
    /** 
     * 加入类描写叙述
     * @author		ElongDeo
     * @version		1.0
     * Created		2014年12月18日 下午1:24:27			
     */
    public class UserUtil {
    	public static final ThreadLocal<Principal> principal = new ThreadLocal<Principal>(); 
    	
    	public static Principal getUserPrincipal(){
    		Principal principal = UserUtil.principal.get();
    		return principal;
    	}
    
    	public static String getUserName(){
    		String userName = "";
    		Principal principal = getUserPrincipal();
    		if(principal!=null){
    			userName = principal.getUsername();
    		}
    		return userName;
    	}
    	
    	public static String getName(){
    		String name = "";
    		Principal principal = getUserPrincipal();
    		if(principal!=null){
    			name = principal.getName();
    		}
    		return name;
    	}
    	
    	public static Long getUserId(){
    		Long userId = null;
    		Principal principal = getUserPrincipal();
    		if(principal!=null){
    			userId = principal.getId();
    		}
    		return userId;
    	}
    	
    	public static Integer getUserType(){
    		Integer userType = null;
    		Principal principal = getUserPrincipal();
    		if(principal!=null){
    			userType = principal.getUserType();
    		}
    		return userType;
    	}
    	
    	public static Long getPharmacyId(){
    		Long pharmacyId = null;
    		Principal principal = getUserPrincipal();
    		if(principal!=null){
    			pharmacyId = principal.getPharmacyId();
    		}
    		return pharmacyId;
    	}
    	
    	public static Long getSaleManId(){
    		Long saleManId = null;
    		Principal principal = getUserPrincipal();
    		if(principal!=null){
    			saleManId = principal.getSaleManId();
    		}
    		return saleManId;
    	}
    	
    	public static Long getYdId(){
    		Long ydId = null;
    		Principal principal = getUserPrincipal();
    		if(principal!=null){
    			ydId = principal.getYdId();
    		}
    		return ydId;
    	}
    	
    	public static Long getBuyerId(){
    		Long buyerId = null;
    		Integer userType = getUserType();
    		if(userType != null && userType > Constants.USER_ADMIN_TYPE){
    			if(userType.equals(Constants.USER_PHARMARY_TYPE)){
    				buyerId = getPharmacyId();
    			}else{
    				buyerId = getYdId();
    			}
    		}
    		return buyerId;
    	}
    	
    	public static String getCartYn(){
    		String cartYn = "no";
    		Integer userType = getUserType();
    		if(userType > Constants.USER_ADMIN_TYPE){
    			cartYn = "yes";
    		}
    		return cartYn;
    	}
    	
    }
    

    cookies工具类(用来封装/解析用户信息)

    /**
     * CookieUtils.java Copyright © 2008-2013 lefeng.com Inc. All Rights Reserved.
     */
    package com.xxx.commons.framework.utils;
    
    
    import java.util.HashMap;
    import java.util.Map;
    
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.commons.codec.binary.Base64;
    
    import com.xxx.commons.framework.bean.Principal;
    import com.xxx.commons.items.PropertiesFileLoader;
    
    /**
     * <pre>
     * <P>Author : ElongDeo</P> 
     * <P>Date : 2014-3-10 </P>
     * <P>Cookie操作辅助类</P>
     * </pre>
     */
    public class CookieUtils {
    	public static String DOMAIN = ".xxx.com";
    	public static final String COOKIE_TOKEN_LOGIN = "xxx_token";
    	public static final String COOKIE_USER_INFO = "xxx_user";
    	
    	static {
    		PropertiesFileLoader instance = PropertiesFileLoader.getInstance();
    		DOMAIN = instance.getProerties("config/user.properties","domain");
    	}
    	/**
    	 * 设置cookie
    	 * @param response
    	 * @param name  cookie名字
    	 * @param value cookie值
    	 * @param maxAge cookie生命周期  以秒为单位
    	 */
    	public static void addCookie(HttpServletResponse response,String name,String value,int maxAge, String domain){
    	    Cookie cookie = new Cookie(name,value);
    	    cookie.setDomain(domain);
    	    cookie.setPath("/");
    	    if(maxAge>0)  cookie.setMaxAge(maxAge);
    	    response.addCookie(cookie);
    	}
    	
    	/**
    	 * 依据名字获取cookie
    	 * @param request
    	 * @param name cookie名字
    	 * @return
    	 */
    	public static Cookie getCookieByName(HttpServletRequest request,String name){
    	    Map<String,Cookie> cookieMap = readCookieMap(request);
    	    if(cookieMap.containsKey(name)){
    	        Cookie cookie = (Cookie)cookieMap.get(name);
    	        return cookie;
    	    }else{
    	        return null;
    	    }   
    	}
    	
    	/**
    	 * 将cookie封装到Map里面
    	 * @param request
    	 * @return
    	 */
    	public static Map<String,Cookie> readCookieMap(HttpServletRequest request){  
    	    Map<String,Cookie> cookieMap = new HashMap<String,Cookie>();
    	    Cookie[] cookies = request.getCookies();
    	    if(null!=cookies){
    	        for(Cookie cookie : cookies){
    	            cookieMap.put(cookie.getName(), cookie);
    	        }
    	    }
    	    return cookieMap;
    	}
    	
    	public static Principal getPrincipal(HttpServletRequest request) {
    		Cookie cookie = getCookieByName(request, COOKIE_USER_INFO);
    		if (cookie != null && !"".equals(cookie.getValue())) {
    			try {
    				return (Principal) SerializeUtils.deserialize(Base64.decodeBase64(cookie.getValue()));
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    		}
    		return null;
    	}
    	
    	public static void setPrincipal(HttpServletResponse response, Principal principal) {
    		try {
    			addCookie(response, COOKIE_USER_INFO, Base64.encodeBase64String(SerializeUtils.serialize(principal)), 0, DOMAIN);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	
    	public static void removePrincipal(HttpServletResponse response) {
    		try {
    			addCookie(response, COOKIE_USER_INFO, null, 0, DOMAIN);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	
    }
    


    登录写入cookie代码片段

    			Principal principal = new Principal(userId,  login, userType, pharmacyId, saleManId, ydId, name);
    			//假设正确,那么写cookie而且正确跳转
    			try {
    				
    				CookieUtils.setPrincipal(response, principal);
    				redirect = StringUtils.isEmpty(request.getParameter("redirect"))?

    LOGIN_REDIRECT_URL:request.getParameter("redirect");// 须要处理首页 PrintUtils.printToMobile(response, new ResultObject<Object>(1, redirect), "json"); return; } catch (Exception e) { e.printStackTrace(); }


    过滤器获取用户信息并放入ThreadLocal

    /**
     * 
     */
    package com.xxx.commons.framework.filters;
    
    import java.io.IOException;
    import java.util.HashSet;
    import java.util.Set;
    
    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.log4j.Logger;
    
    import com.xxx.commons.framework.utils.CookieUtils;
    import com.xxx.commons.framework.utils.StringUtils;
    import com.xxx.commons.framework.utils.UserUtil;
    
    
    
    /**
     * Servlet Filter implementation class AuthenticationFilter
     */
    public class PrincipalFilter implements Filter {
    	
    	Logger logger = Logger.getLogger(PrincipalFilter.class);
    	private static String notLoginUrl = null;
    
    	// 被忽略的全部URL.
    	private static Set<String> mobjIgnoredUrls = new HashSet<String>();
    
    	/**
    	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
    	 */
    	public void doFilter(ServletRequest request, ServletResponse response,
    			FilterChain chain) throws IOException, ServletException {
    		UserUtil.principal.set(CookieUtils.getPrincipal((HttpServletRequest)request));
    		if(notLoginUrl != null && UserUtil.principal.get() == null && !isIgnoreUrl((HttpServletRequest)request)){
    			((HttpServletResponse)response).sendRedirect(notLoginUrl);
    			return;
    		}
    		chain.doFilter(request, response);
    	}
    
    	/**
    	 * 加入描写叙述 
    	 * @author ElongDeo 2015年6月26日
    	 * @param filterConfig
    	 * @throws ServletException
    	 */
    	@Override
    	public void init(FilterConfig filterConfig) throws ServletException {
    		notLoginUrl = filterConfig.getInitParameter("notLoginUrl");
    		// 包装要被忽略的URL
    		String urlText = filterConfig.getInitParameter("ignoredUrls");
    		if(urlText != null){
    			urlText = urlText.replaceAll("
    ", "").replaceAll("	", "").trim();
    			String[] urls = urlText.split(",");
    			for (int i = 0; i < urls.length; i++) {
    				mobjIgnoredUrls.add(urls[i]);
    			}
    		}
    	}
    	/**
    	 * <pre>
    	 * 验证是否要被忽略的URL.
    	 * </pre>
    	 * 
    	 * @param pobjRequest
    	 *            the pobjRequest
    	 * @return true, if is ignore url
    	 * @author guotianchi 2011-4-20
    	 */
    	private boolean isIgnoreUrl(HttpServletRequest pobjRequest) {
    		String objRequestUri = pobjRequest.getRequestURI();
    		if (StringUtils.isNotEmpty(objRequestUri)) {
    			int index = objRequestUri.lastIndexOf('/');
    			if (index >= 0
    					&& index < (objRequestUri.length() - 1)
    					&& mobjIgnoredUrls.contains(objRequestUri.substring(
    							index + 1, objRequestUri.length()))) {
    				return true;
    			}
    		}
    		return false;
    	}
    
    	/**
    	 * 加入描写叙述 
    	 * @author ElongDeo 2015年6月26日
    	 */
    	@Override
    	public void destroy() {
    	}
    }
    

    应用serverweb.xml配置

        <filter>
    		<filter-name>PrincipalFilter</filter-name>
    		<filter-class>com.xxx.commons.framework.filters.PrincipalFilter</filter-class>
    		<init-param>
    			<param-name>notLoginUrl</param-name>
    			<param-value>/common/logout.htm</param-value>
    		</init-param>
    		<init-param>
    			<param-name>ignoredUrls</param-name>
    			<param-value>logout.htm</param-value>
    		</init-param>
    	</filter>
    
        <filter-mapping>
    		<filter-name>PrincipalFilter</filter-name>
    		<url-pattern>/*</url-pattern>
    	</filter-mapping>


  • 相关阅读:
    QuickTest Professional对web网站进行测试后没有生成脚本信息解决办法
    如何使用loadrunner进行web网站性能测试
    spring boot架构浅谈
    spring cloud架构
    crontab误删操作的恢复与防范
    linux命令重定向>、>>、 1>、 2>、 1>>、 2>>、 <
    redis原理及使用
    PHP三种字符串界定符的区别(单引号,双引号,<<<)
    php代码加密|PHP源码加密——实现方法
    java一键搭建新项目(地址)
  • 原文地址:https://www.cnblogs.com/lxjshuju/p/6939460.html
Copyright © 2020-2023  润新知