基于token的身份验证JWT

一、概念:

  JWT:Json Web Token。JWT 是JSON风格轻量级的授权和身份认证规范,可实现无状态、分布式的Web应用授权。是基于token的一种授权认证方式。就是一个字符串,经过加密处理与校验处理的字符串。JWT可以使用HMAC算法或者是RSA的公私秘钥对进行签名。简洁(Compact): 可以通过URL,POST参数或者在HTTP header发送,因为数据量小,传输速度也很快 自包含(Self-contained):负载中包含了所有用户所需要的信息,避免了多次查询数据库。

二、token应用流程为:

1、初次登录:用户初次登录,输入用户名密码。

2、密码验证:服务器从数据库取出用户名和密码进行验证。

3、生成JWT:服务器端验证通过,根据从数据库返回的信息,以及预设规则,生成JWT。

4、返还JWT:服务器的HTTP RESPONSE中将JWT返还。

5、带JWT的请求:以后客户端发起请求,HTTP REQUEST HEADER中的Authorization字段都要有值,为JWT,用来验证用户身份以及对路由,服务和资源的访问权限进行验证。

三、JWT的结构

JWT包含了使用.分隔的三部分: Header 头部 Payload 负载 Signature 签名,它的结构是这样的Header.Payload.Signature,中间以.来分割。

 

Header

Header格式为:

{

    "typ": "JWT",

    "alg": "HS256"

}

在header中通常包含了两部分:token类型和采用的加密算法。它就是一个json串,两个字段是必须的,不能多也不能少。alg字段指定了生成C的算法,默认值是HS256,对这部分内容使用 Base64Url 编码组成了JWT结构的第一部分。

 

Payload

Token的第二部分是负载,根据JWT claim set用base64加密得到的,它包含了claim, Claim是一些实体(通常指的用户)的状态和额外的元数据。claim set是一个json数据,是表明用户身份的数据,可自行指定字段很灵活,也有固定字段表示特定含义。常用的字段有 iss(签发者),exp(过期时间戳), sub(面向的用户), aud(接收方), iat(签发时间),jti(JWT ID,针对当前token的唯一标识)等。,将claim set加密后得到负载,经过Base64Url编码后作为JWT结构的第二部分。

 

Signature

创建签名需要使用编码后的header和payload以及一个秘钥,使用header中指定签名算法进行签名。例如如果希望使用HMAC SHA256算法,那么签名应该使用下列方式创建: HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret) 签名用于验证消息的发送者以及消息是没有经过篡改的。完整的JWT格式的输出是以 . 分隔的三段Base64编码,JWT在HTTP和HTML环境中更容易传递。签名其实就是一个字符串。作用类似于CRC校验,保证加密没有问题。

JWT工具类代码:

public class JWT {
@Value("${spring.profiles.active}")
private static String profiles;
@Value("${jwt_secret}")
private static String jwt_secret;
public static SecretKey generalKey(){
String stringKey = profiles + jwt_secret;
byte[] encodedKey = Base64.decodeBase64(stringKey);
SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
return key;
}
public static String createJWT(String id, String subject, long ttlMillis, Map<String, Object> claims){
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
SecretKey key = generalKey();
JwtBuilder builder = Jwts.builder()
.setId(id)
.setIssuedAt(now)
.setSubject(subject)
.signWith(signatureAlgorithm, key);
if(claims != null && !claims.isEmpty()) {
builder.setClaims(claims);
}
if (ttlMillis >= 0) {
long expMillis = nowMillis + ttlMillis;
Date exp = new Date(expMillis);
builder.setExpiration(exp);
}
return builder.compact();
}

public static Claims parseJWT(String jwt){
SecretKey key = generalKey();
Claims claims = Jwts.parser()
.setSigningKey(key).setAllowedClockSkewSeconds(3600 * 24)
.parseClaimsJws(jwt).getBody();
return claims;

}
}

猜你喜欢

转载自www.cnblogs.com/wanghaichao/p/9201061.html