萱草|记一次token安全认证的实践

背景介绍:
因项目需求 , 有PC端APP端和小程序端 , 但登陆接口是同一个 , 然而微服务也无法使用传统的session解决用户登录问题(注意这里是传统的session不是springsession) , 使用户信息在其他服务共享 。
如此一来就想到了token安全认证 , 而JWT生成token可以包含用户信息 , 也就果断选择了JWT作为SpringCloudgateway网关的token校验工具 , 这样 , 我们便可以直接解析token获取用户信息了 。
具体实现思路:
让JWT在其他所有服务可以共同使用 , 父工程需要引入JWTjar 。 避免在其他服务重复引入 。 如何使用JWT生成token 。 如何解析token 。 如何让网关拦截用户请求校验token 。 如何避免首次登录被网关拦截 。代码实现:
1.创建SpringCloud项目
SpringCloud子项目包含eureka , gateway , auth三个工程 , 父工程maven依赖如下 。
<dependency>
<groupId>com.nimbusdsgroupId>
<artifactId>nimbus-jose-jwtartifactId>
<version>6.0version>
dependency>
2.Auth和gateway编写TOKEN工具类
publicclassToken{
privatestaticfinalLoggerlog=LoggerFactory.getLogger(Token.class);
/**
*1.创建一个32-byte的密匙JWT生成TOKEN
*/
privatestaticfinalbyte[]secret="geiwodiangasfdjsikolkjikolkijswe".getBytes();
//生成一个token
publicstaticStringcreatToken(MappayloadMap)throwsJOSEException{
//3.先建立一个头部Header
/**
*JWSHeader参数:1.加密算法法则,2.类型 , 3. 。。。。。。。
*一般只需要传入加密算法法则就可以 。
*这里则采用HS256
*JWSAlgorithm类里面有所有的加密算法法则 , 直接调用 。
*/
JWSHeaderjwsHeader=newJWSHeader(JWSAlgorithm.HS256);
//建立一个载荷Payload
Payloadpayload=newPayload(newJSONObject(payloadMap));
//将头部和载荷结合在一起
JWSObjectjwsObject=newJWSObject(jwsHeader,payload);
//建立一个密匙
JWSSignerjwsSigner=newMACSigner(secret);
//签名
jwsObject.sign(jwsSigner);
//生成token
returnjwsObject.serialize();
}
/**
*解析一个token
*@paramtoken
*@return
*@throwsParseException
*@throwsJOSEException
*/
publicstaticMapvalid(Stringtoken)throwsParseException,JOSEException{
//解析token
JWSObjectjwsObject=JWSObject.parse(token);
//获取到载荷
Payloadpayload=jwsObject.getPayload();
//建立一个解锁密匙
JWSVerifierjwsVerifier=newMACVerifier(secret);
MapresultMap=newHashMap<>();
//判断token
if(jwsObject.verify(jwsVerifier)){
resultMap.put("Result",0);
//载荷的数据解析成json对象 。
JSONObjectjsonObject=payload.toJSONObject();
resultMap.put("data",jsonObject);
//判断token是否过期
if(jsonObject.containsKey("exp")){
LongexpTime=Long.valueOf(jsonObject.get("exp").toString());
LongnowTime=newDate().getTime();
//判断是否过期
if(nowTime>expTime){
//已经过期
resultMap.clear();
resultMap.put("Result",2);
}
}
}else{
resultMap.put("Result",1);
}
returnresultMap;
}
/**
*生成token的业务逻辑登录接口调用次业务
*@paramuid
*@return
*/
publicstaticStringTokenTest(Longuid,LongdeptId,StringuserType,intcompanyId){