微服务--权限校验(jwt)
第一次写博客有点紧张,还有点小激动,话不多说直接切入正题什么是JWT(JSON WEB TOKENS)?JWT是一种用于双方之间传递安全信息的简洁的、URL安全的表述性声明规范。JWT作为一个开放的标准(RFC 7519),定义了一种简洁的,自包含的方法用于通信双方之间以Json对象的形式安全的传递信息。因为数字签名的存在,这些信息是可信的,JWT可以使用HMAC算法或者是RSA的公私秘钥对进行签
第一次写博客有点紧张,还有点小激动,话不多说直接切入正题
什么是JWT(JSON WEB TOKENS)?
JWT是一种用于双方之间传递安全信息的简洁的、URL安全的表述性声明规范。JWT作为一个开放的标准(RFC 7519),定义了一种简洁的,自包含的方法用于通信双方之间以Json对象的形式安全的传递信息。因为数字签名的存在,这些信息是可信的,JWT可以使用HMAC算法或者是RSA的公私秘钥对进行签名。简洁(Compact): 可以通过URL,POST参数或者在HTTP header发送,因为数据量小,传输速度也很快 自包含(Self-contained):负载中包含了所有用户所需要的信息,避免了多次查询数据库
简单介绍JWT之后,这篇文章不详细讲解JWT,如果想详细了解JWT请关注后续博客
好了,JWT理解为传递安全信息的一种声明规范就可以了,我会从登陆生成token到认证详细进行说明,欢迎大家指明不足,也可以一起讨论----本次案例是微服务的登陆权限校验
首先微服务的知识我不在这里普及,先贴代码
/**
* 创建jwt
* @param id
* @param subject
* @param ttlMillis 过期的时间长度
* @return jwt
*/
public static String createJWT(String id,String subject,long ttlMillis){
//指定签名时候使用的签名算法,也就是header那部分,jjwt已经将这部分内容封装好了
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS512;
//生成JWT的时间
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
//创建payload的私有声明(根据特定的业务需要添加,如果要拿这个做验证,一般是需要和jwt的接收方提前沟通好验证方式的)
Map<String,Object> clamis = new HashMap<String,Object>();
clamis.put("uid","123456");
clamis.put("user_name","admin");
clamis.put("nickName","DASDA121");
//生成签名的时候使用的密钥secret,这个方法在本地封装一般可以从本地配置文件中读取,切记这个秘钥不能外露哦。
// 它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。
String key = generalKey();
//下面就是为payload添加各种标准申明和私有声明了
JwtBuilder builder = Jwts.builder()
.setClaims(clamis)//如果有私有声明,一定要先设置这个自己创建的私有声明这个是给builder的claim赋值,
// 一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的
.setId(id) //设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,
// 主要用来作为一次性token,从而回避重放攻击。
.setIssuedAt(now) //iat: jwt的签发时间
.setSubject(subject) //sub(Subject):代表这个JWT的主体,即它的所有人,这个是一个json格式的字符串
// ,可以存放什么userid,roldid之类的,作为什么用户的唯一标志。
.signWith(signatureAlgorithm,key);//设置签名使用的签名算法和签名使用的秘钥
if (ttlMillis >= 0) {
long expMillis = nowMillis + ttlMillis;
Date exp = new Date(expMillis);
builder.setExpiration(exp); //设置过期时间
}
return builder.compact();
}
以上是创建token 基于JWT声明规范(注释很多我就不再赘述),其中generalKey()方法没有贴出来,是生成签名的密钥,
可以自己定义运用一些加密算法生成字符串,不过认证的时候还要用到该密钥,所以前后要保持一致。
然后什么时候认证?肯定是每次访问我们接口的时候,请求每次放入头部,
因为本次案例是微服务,认证这块肯定放在网关(zuul)统一处理,详细代码如下:
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
log.info("send {} request to{}", request.getMethod(), request.getRequestURL().toString());
String access_Token =request.getHeader("access_token");
if(access_Token == null || access_Token.equals("")){
log.warn("accessToken is empty");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(405);
try {
ctx.getResponse().getWriter().write("accessToken is empty");
} catch (Exception e) {
}
return ResultVOUtil.error(405,"accessToken is empty");
}else{
Claims claims = null;
try {
//解密JWT
claims = JwtUtil.parseJWT(access_Token);
} catch (Exception e) {
log.warn("accessToken is ERRO");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(405);
try {
ctx.getResponse().getWriter().write("accessToken is ERRO");
} catch (IOException e1) {
e1.printStackTrace();
}
return ResultVOUtil.error(405,"accessToken is ERRO");
}
log.warn("accessToken is ok");
return true;
以上是认证过程,解密token如下:
/**
* 解密jwt
* @param jwt
* @return
* @throws Exception
*/
public static Claims parseJWT(String jwt) throws Exception{
String key = generalKey(); //签名秘钥,和生成的签名的秘钥一模一样
Claims claims = Jwts.parser() //得到DefaultJwtParser
.setSigningKey(key) //设置签名的秘钥
.parseClaimsJws(jwt).getBody();//设置需要解析的jwt
return claims;
}
以上代码可以使用,如有疑问的话请加本人微信:a1498470355 欢迎一起讨论,
下一篇我会讲解微服务SpringCloud+Eureka
更多推荐
所有评论(0)