1.JWT介绍
JWT(JSON Web Token)是一种基于JSON格式的身份验证和授权标准,经常用于Web应用程序中的用户身份验证。JWT由三个部分组成:头部、载荷和签名。头部包含算法和类型信息,载荷包含用户数据和元数据,签名则是基于头部和载荷计算得出的,在身份验证时用于验证请求是否是合法的。
JWT是一种轻量级、简单、可扩展的身份验证机制,具有良好的互操作性和各种编程语言中的广泛支持。可以在前端使用JavaScript生成JWT并在后端进行验证,也可以在后端使用Java、Python等语言生成和验证JWT。同时,JWT具有良好的安全性能,防止了跨站点脚本(XSS)和跨站点请求伪造(CSRF)等攻击。
1.1JWT的主要用于两个用途:
- 数据交换:因为JWT使用JSON来存储相关数据,而JSON这一种数据格式可以在各方之间传递。
- 安全验证:登录之后,后续的请求可以携带JWT,只有携带了JWT(认证Token)的请求才能够正常地访问到相关的数据及资源。
一般我们在开发过程中,凡是涉及到用户登录的,我们就需要去考虑用什么去存储用户登录的一个状态,两种策略:
- session(基于cookie的实现):只不过session相关的数据存储于服务器。采用session这种方式,是以本地缓存来存储相关的数据的,当有100个用户进行登录的时候,就需要在本地缓存存储100个信息。因此会给服务器带来一定的内存压力。
- JWT:一旦生成,一般就抛给客户端去保存。客户端只需要每次携带这个Token就可以正常地访问接口。
1.2JWT的优点
- 无状态:服务器不需要在会话中存储任何会话信息,从而降低了服务器的资源开销,也提高了可扩展性;
- 可扩展性:JWT以JSON为数据格式,可以存储各种格式的数据,例如数组、嵌套JSON对象等,非常适合扩展;
- 安全性好:JWT支持签名和加密机制,可以防止请求被篡改或伪造。
- 跨平台支持:JWT是基于JSON格式的标准,并且是独立于编程语言的,非常适合跨平台使用。
1.3JWT的缺点
- 安全性取决于密钥的保护:JWT的安全性取决于密钥的保护,如果密钥泄漏,攻击者就可以伪造有效的JWT,从而通过身份验证。
- 载荷不能加密:JWT中的载荷是未加密的,因此可能会将敏感数据暴露给未经授权的人员。
总之,JWT以其轻量级、可扩展、跨平台的优点成为了Web应用程序中常用的身份验证机制,但在使用时需要注意密钥的保护以及不将敏感数据放在JWT的载荷中。
2JWT 使用
2.1依赖
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.2.2</version>
</dependency>
2.2代码
package com.lys.lys_admin_api.common.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.Calendar;
/**
* jwt 在线解析 http://jwt.calebb.net/
*/
public class JWTUtils {
public static final String SECRET = "liuyunshengsir";
public static void main(String[] args) {
String a="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyTmFtZSI6ImxpdXl1bnNoZW5nc2lyIiwiZXhwIjoxNjg0ODk2MDI2LCJ1c2VySWQiOiIxMTExMTExIn0.nMQiL9wRaDyRCf1zD1HL9vEixWNGR4AiDt0JCJcB5GE";
getJWT();
readJWT(a);
}
public static String getJWT(){
Calendar expires = Calendar.getInstance();
expires.add(Calendar.SECOND, 60);
String jwtToken = JWT.create()
// 第一部分Header
.withHeader(null)
// 第二部分Payload
.withClaim("userId", "1111111")
.withClaim("userName", "liuyunshengsir")
.withExpiresAt(expires.getTime())
// 第三部分Signature
.sign(Algorithm.HMAC256(SECRET));
System.out.println(jwtToken);
return jwtToken;
}
public static void readJWT(String str){
// 创建一个验证的对象
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
DecodedJWT verify = jwtVerifier.verify(str);
System.out.println(verify.getClaim("userId").asString());
System.out.println(verify.getClaim("userName").asString());
System.out.println("过期时间:" + verify.getExpiresAt());
}
}
3.异常
常见的异常
这里贴出4个常见的异常,如果JWT校验不通过,就会抛出异常:
- SignatureVerificationException:签名不一致。
- TokenExpiredException:令牌过期。
- AlgorithmMismatchException:算法不匹配异常。
- InvalidClaimException:失效的Payload异常。一般存在于这种情况:获取token的服务器比使用token的服务器时钟快,请求分发到时间慢的服务器上导致token还没生效。