在token前后端分离中,后台token工具类设计实现:
依赖jar包
gradle配置:
//token util tools jar
compile ‘com.nimbusds:nimbus-jose-jwt:5.4’
生成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)));
}
}
跨域接收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