token实现及前后端分离对接后台配置实现

在token前后端分离中,后台token工具类设计实现:

  1. 依赖jar包
    gradle配置:
    //token util tools jar
    compile ‘com.nimbusds:nimbus-jose-jwt:5.4’

  2. 生成token、校验token和解析token用户信息

     import java.util.Date;
     import java.util.HashMap;
     import java.util.Map;
     import org.apache.commons.lang3.StringUtils;
     import org.springframework.util.CollectionUtils;
     import com.google.gson.Gson;
     import com.nimbusds.jose.JWSAlgorithm;
     import com.nimbusds.jose.JWSHeader;
     import com.nimbusds.jose.JWSObject;
     import com.nimbusds.jose.JWSSigner;
     import com.nimbusds.jose.JWSVerifier;
     import com.nimbusds.jose.Payload;
     import com.nimbusds.jose.crypto.MACSigner;
     import com.nimbusds.jose.crypto.MACVerifier;
     import net.minidev.json.JSONObject;
     
     /**
      * token工具类
      *
      * @author ***
      * @version Created:2018年12月26日
      * 
      */
     public class TokenUtil {
     
     	/****
     	 * 依赖jar包: 
     	 * compile com.nimbusds:nimbus-jose-jwt:5.4 compile
     	 * com.google.code.gson:gson:2.8.5
     	 */
     	/**
     	 * 1.创建一个32-byte的密匙
     	 */
     
     	private static final byte[] SECRET_KEY = "xxxxxxxxxxx".getBytes();
     
     	/****
     	 * token创建时间 (避免key被自定义保存数据覆盖)
     	 */
     	private static final String CREATE_TIME_KEY = "__cas_create_time";
     
     	/****
     	 * token失效时间
     	 */
     	private static final String INVALID_TIME_KEY = "__cas_invalid_time";
     
     	/****
     	 * 生成token
     	 * 
     	 * @param payloadMap
     	 *            用户数据信息
     	 * @param invalidTime
     	 *            失效时间
     	 * @return
     	 */
     	public static String createToken(Map payloadMap, long createTime, long invalidTime) {
     		try {
     			if (invalidTime < createTime) {
     				System.out.println("====> 失效时间必须大于创建时间...");
     				return null;
     			}
     			if (CollectionUtils.isEmpty(payloadMap)) {
     				payloadMap = new HashMap();
     			}
     			payloadMap.put(CREATE_TIME_KEY, System.currentTimeMillis());
     			payloadMap.put(INVALID_TIME_KEY, invalidTime);
     			System.out.println("====> 生成token用户信息为:" + GsonUtil.toJson(payloadMap));
     			// 3.先建立一个头部Header
     			/**
     			 * JWSHeader参数:1.加密算法法则,2.类型,3.其它 一般只需要传入加密算法法则就可以。 这里则采用HS256
     			 * 
     			 * Payload 建立一个载荷
     			 *
     			 * JWSAlgorithm类里面有所有的加密算法法则,直接调用。
     			 */
     			// 将头部和载荷结合在一起
     			JWSObject jwsObject = new JWSObject(new JWSHeader(JWSAlgorithm.HS256),
     					new Payload(new JSONObject(payloadMap)));
     
     			// 建立一个密匙
     			JWSSigner jwsSigner = new MACSigner(SECRET_KEY);
     			// 签名
     			jwsObject.sign(jwsSigner);
     
     			// 生成token
     			return jwsObject.serialize();
     		} catch (Exception e) {
     			System.out.println("====> 创建token失败:" + e);
     			e.printStackTrace();
     			return null;
     		}
     	}
     
     	/****
     	 * 解析出token的Payload部分数据信息
     	 * 
     	 * @param token
     	 * @return
     	 * @since 2018.12.26
     	 */
     	public static Map parsePayloadData(String token) {
     		try {
     			if (StringUtils.isEmpty(token)) { 
     				return null;
     			}
     			// 解析token
     			JWSObject jwsObject = JWSObject.parse(token);
     			// 获取到载荷
     			Payload payload = jwsObject.getPayload();
     			// 建立一个解锁密匙
     			JWSVerifier jwsVerifier = new MACVerifier(SECRET_KEY);
     
     			Map resultMap = null;
     			// 判断token
     			if (jwsObject.verify(jwsVerifier)) { // 校验成功(未校验是否过期)
     				// 载荷的数据解析成json对象。
     				JSONObject jsonObject = payload.toJSONObject();
     				Gson gson = new Gson();
     				resultMap = gson.fromJson(gson.toJson(jsonObject), Map.class);
     			}
     			return resultMap;
     		} catch (Exception e) {
     			System.out.println("====> 解析token失败: " + e);
     			e.printStackTrace();
     			return null;
     		}
     	}
     
     	/****
     	 * 校验token是否过期
     	 * 
     	 * @param token
     	 * @return 0-有效 1-失效 2-校验失败
     	 * @since 2018.12.26
     	 */
     	public static boolean validToken(String token) {
     		try {
     			if (StringUtils.isEmpty(token)) {
     				return false;
     			}
     			// 解析token
     			JWSObject jwsObject = JWSObject.parse(token);
     
     			// 获取到载荷
     			Payload payload = jwsObject.getPayload();
     
     			// 建立一个解锁密匙
     			JWSVerifier jwsVerifier = new MACVerifier(SECRET_KEY);
     			// 判断token
     			if (jwsObject.verify(jwsVerifier)) {
     				// 载荷的数据解析成json对象。
     				JSONObject jsonObject = payload.toJSONObject();
     				// 判断token是否过期
     				if (jsonObject.containsKey(INVALID_TIME_KEY)) {
     					Long invalidTime = Long.valueOf(jsonObject.get(INVALID_TIME_KEY).toString());
     					Long nowTime = new Date().getTime();
     					System.out.println(" nowTime: " + nowTime + ", invalidTime:" + invalidTime);
     					// 判断是否过期
     					if (invalidTime > nowTime) {
     						System.out.println("token有效");
     						// token有效
     						return true;
     					}
     				}
     			}
     			return false;
     		} catch (Exception e) {
     			System.out.println("====> 解析token失败...");
     			e.printStackTrace();
     			return false;
     		}
     	}
     
     	/**
     	 * 校验token是否合法,返回Map集合,集合中主要包含 state状态码 data鉴权成功后从token中提取的数据
     	 * 该方法在过滤器中调用,每次请求API时都校验
     	 * 
     	 * @param token
     	 * @return Map
     	 */
     	/*public static Map validTipsToken(String token) {
     		Map resultMap = new HashMap();
     		try {
     			JWSObject jwsObject = JWSObject.parse(token);
     			Payload payload = jwsObject.getPayload();
     			JWSVerifier verifier = new MACVerifier(SECRET_KEY);
     
     			if (jwsObject.verify(verifier)) {
     				JSONObject jsonOBj = payload.toJSONObject();
     				// token校验成功(此时没有校验是否过期)
     				resultMap.put("state", TokenState.VALID.toString());
     				// 若payload包含ext字段,则校验是否过期
     				if (jsonOBj.containsKey("ext")) {
     					long extTime = Long.valueOf(jsonOBj.get("ext").toString());
     					long curTime = new Date().getTime();
     					// 过期了
     					if (curTime > extTime) {
     						resultMap.clear();
     						resultMap.put("state", TokenState.EXPIRED.toString());
     					}
     				}
     				resultMap.put("data", jsonOBj);
     
     			} else {
     				// 校验失败
     				resultMap.put("state", TokenState.INVALID.toString());
     			}
     
     		} catch (Exception e) {
     			// e.printStackTrace();
     			// token格式不合法导致的异常
     			resultMap.clear();
     			resultMap.put("state", TokenState.INVALID.toString());
     		}
     		return resultMap;
     	}*/
     
     	public static void main(String[] args) {
     		Map sessionUser = new HashMap();
     		sessionUser.put("loginName", "admin");
     		sessionUser.put("email", "[email protected]");
     		sessionUser.put("phone", "15801306497");
     		// 单元测试1:success
     		long createTime = new Date().getTime();
     		long invalidTime = new Date().getTime() + 10 * 60 * 1000;
     		String token = createToken(sessionUser, createTime, invalidTime);
     		System.out.println("生成token1:" + token);
     		// 单元测试2:sessionUser 为null
     		String token2 = createToken(null, createTime, invalidTime);
     		System.out.println("生成token2: " + token2);
     
     		System.out.println("token1是否有效:" + validToken(token));
     		System.out.println("token2是否有效:" + validToken(token2));
     		// 解析用户信息
     		Map parseUser = parsePayloadData(token);
     		System.out.println("====> 解析token1用户信息为:" + new Gson().toJson(parseUser));
     		parseUser = parsePayloadData(token2);
     		System.out.println("====> 解析token2的用户信息为:" + new Gson().toJson(parseUser));
     
     		// 单元测试3:token失效
     		String token3 = createToken(sessionUser, createTime, System.currentTimeMillis());
     		System.out.println("生成token3: " + token3);
     		System.out.println("token3是否有效:" + validToken(token3));
     		System.out.println("解析token3的用户信息为:" + new Gson().toJson(parsePayloadData(token3)));
     
     	}
     }
    
  3. 跨域接收token参数配置

     public class CorsFilter implements Filter {
        public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
     	   	HttpServletResponse response = (HttpServletResponse) res;
             log.info("====>调用到此方法...");
      
             HttpServletRequest request = (HttpServletRequest) req;       
             log.info("====> " + request.getRequestURI() + " X-Requested-With: " + request.getHeader("X-Requested-With"));
             String token = RequestUtils.getHeaderToken(request, AppConstants.RISK_ACCESS_TOKEN);
             System.out.println("====> token: " + token);
             
             response.setHeader("Access-Control-Allow-Origin",request.getHeader("Origin"));
             response.setHeader("Access-Control-Allow-Credentials", "true");
             response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE,PUT");
     //        response.setHeader("Access-Control-Max-Age", "3600");
             response.setHeader("Access-Control-Allow-Headers", "**cas_access_token**,X-Requested-With,Content-Type");
             //response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token");
     	   //}
     	   //index++;
             chain.doFilter(request, response);
         }
         public void init(FilterConfig filterConfig) {}
         public void destroy() {}
     }
    

其中,cas_access_token是token的key。

参考网址:@link http://www.cnblogs.com/dragonetyu/p/7591745.html

你可能感兴趣的:(技术解决方案)