- 什么是JJWT?
JJWT是一个提供端到端的JWT创建和验证的Java库。永远免费和开源(Apache License,版本2.0),JJWT很容易使用和理解。它被设计成一个以建筑为中心的流畅界面,隐藏了它的大部分复杂性。
- 什么是JSON Web Token(JWT)
JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。和 Cookie-Session 的模式不同,JSON Web Token(JWT)使用 Token 替换了 SessionId 的资源访问和状态的保持。
- JWT的组成
Jwt由头部、载荷、签名三部分组成,头部包含元数据,通常用来记录JWT所用的算法。
例如:
Header:
{
"typ": "JWT",
"alg": "HS256"
}
将这个头部使用Base64编码过后,就得到的JWT的第一段字符串
载荷:载荷用来承载JWT中的有效信息,通常包括三部分
- 公共的声明
可以存放自定义的信息,但是由于载荷仍旧使用的Base64进行编码,所以不建议在载荷中存放敏感信息。
- 私密的声明
私密的声明用来存放提供者和消费者共同定义的数据。但是由于载荷仍旧使用的Base64进行编码,所以不建议在载荷中存放敏感信息。
- 标准中注册的声明
iss:jwt的签发者
sub:jwt的面向用户
aud: 接收jwt的一方
exp: jwt的过期时间
nbf: 定义在什么时间之前,该jwt都是不可用的.
iat: jwt的签发时间
jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
将载荷进行base64编码之后,得到第二部分字符串,不建议在载荷中存放过多的数据。
签名:签名用来防止载荷中的数据被篡改,使用头部+载荷中的编码和秘钥一起加密之后生成签名,一旦知道了秘钥,会导致任何人都可以随意的签发token,所以要保护好秘钥。
- JWT的优势
- 支持跨域:由JWT生成的Token可以通过存放在HTTP头中进行传输,而Cookie是不允许跨域传输的。
- 无状态:使用token访问时,可以使用token来承载信息,而不需要在服务端生成session来存放生成的信息。
- 支持移动应用:由于在移动端是不存在Cookie的,所以使用Token可以解决没有Cookie所带来的的问题。
- CSRF:因为不再依赖于Cookie,所以你就不需要考虑对CSRF(跨站请求伪造)的防范。(如果token是用cookie保存,CSRF还是需要考虑,一般建议使用1、在HTTP请求中以参数的形式加入一个服务器端产生的token。或者2.放入http请求头中也就是一次性给所有该类请求加上csrftoken这个HTTP头属性,并把token值放入其中)
- JWT的使用方式
- 在请求参数中添加token
由于不在Cookie中保存token,可以防止CSRF攻击,防止攻击者伪造用户信息。
- 在Http头中添加属性
在Http头中添加属性,可以防止token被记录到浏览器的地址栏,防止token泄露。
- JJWT的实现
- maven下载jar包
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
- 生成JJWT的token
public String createToken(Map<String, Object> claims, String subject,HttpServletRequest request) {
List<Addressable> addressList = tokenService.getAddressable();
logger.info(addressList.toString());
String ipAddress = CusAccessObjectUtil.getIpAddress(request);
logger.info(ipAddress);
for (Addressable addressable : addressList) {
if (ipAddress.equals(addressable.getIp())) {
// 指定签名的时候使用的签名算法,也就是header那部分,jjwt已经将这部分内容封装好了。
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
// 获取系统目前时间
long nowMillis = System.currentTimeMillis();
// 转换成Date
Date now = new Date(nowMillis);
//获取秘钥
SecretKey key = generalKey();
//设置当前3分钟之后过期
Calendar nowTime = Calendar.getInstance();
nowTime.add(Calendar.MINUTE, 3);
Date expiresDate = nowTime.getTime();
JwtBuilder jwtBuilder = Jwts.builder() //new一个JWT的builder,用来设置JWT的body
.setClaims(claims)//设置这个自己的私有变量
.setExpiration(expiresDate)//设置过期时间
.setId(UUID.randomUUID().toString()) //设置唯一ID防止重放攻击
.setIssuedAt(now) //设置当前
.setSubject(subject)//可以存放userid等内容,用来表明用户的唯一标识
.signWith(signatureAlgorithm, key);
return jwtBuilder.compact();
}
}
return null;
}
- 解析JJWT
public Claims parseJWT(String jwt) {
try {
SecretKey key = generalKey(); //签名秘钥,和生成的签名的秘钥一模一样
Claims claims = Jwts.parser() //得到DefaultJwtParser
.setSigningKey(key) //设置签名的秘钥
.parseClaimsJws(jwt).getBody();//设置需要解析的jwt
return claims;
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
来源:CSDN
作者:艾蕾!
链接:https://blog.csdn.net/xycgyyx/article/details/103471838