1.什么是JWT ==JWT(JSON Web Token)是一种用于身份验证和授权的开放标准。它是一种轻量级的、基于JSON的令牌,可以在客户端和服务器之间传递信息。JWT由三部分组成:头部、载荷和签名。头部包含令牌类型和所使用的算法,载荷包含用户信息和其他元数据,签名用于验证令牌的完整性和真实性。JWT的优点包括可扩展性、可靠性和安全性。==
简单的说,==JWT就是通过数字签名的方式,以JSON对象为载体的开发标准,可以在不同的服务终端之间安全的传输信息。 ==
JWT官网:https://jwt.io/
2.JWT的应用场景
授权 :==这是使用 JWT 的最常见方案。用户登录后,每个后续请求都将包含 JWT,允许用户访问使用该令牌允许的路由、服务和资源。==单点登录是当今广泛使用 JWT 的一项功能,因为它的开销很小,并且能够跨不同域轻松使用。
信息交换 :JSON Web Token是在各方之间安全传输信息的好方法。由于 JWT 可以签名(例如,使用公钥/私钥对),因此您可以确定发件人是他们所说的人。此外,由于签名是使用标头和有效负载计算的,因此您还可以验证内容是否未被篡改。
3.JWT的结构 3.1JWT的结构组成 JSON Web 令牌的紧凑形式由点分隔的三个部分组成,分别是:
因此,JWT 通常如下所示。
Header
Header通常由两部分组成: 令牌的类型(即 JWT)和正在使用的签名算法,例如 HMAC SHA256 或 RSA。
例如:
{
"alg" : "HS256" ,
"typ" : "JWT"
}
然后,此JSON被Base64Url 编码以形成JWT的第一部分。
Payload
令牌的第二部分是有效负载,其中包含声明。声明是有关实体(通常是用户)和其他数据的语句。
示例有效负载可以是:
{
"sub" : "1234567890" ,
"name" : "John Doe" ,
"admin" : true
}
然后对有效负载进行 Base64Url 编码以形成 JSON Web 令牌的第二部分。
请注意,对于签名令牌,此信息虽然受到篡改保护,但任何人都可以读取。不要将机密信息放在 JWT 的有效负载或标头元素中,除非它已加密。
Signature
要创建签名部分,您必须获取Header
、Payload
、secret
以及Header
中指定的算法并对其进行签名。
签名用于验证消息在此过程中未被更改,并且在使用私钥签名的令牌的情况下,它还可以验证 JWT 的发件人是否是它所说的人。
3.2JWT的结构 JWT输出是由点分隔的Header
、Payload
、Signature
的 Base64-URL 字符串,可以在 HTML 和 HTTP 环境中轻松传递,同时与基于 XML 的标准(如 SAML)相比更加紧凑。
下面显示了对以前的标头和有效负载进行了编码并使用机密进行签名的 JWT。
4.JWT如何工作
==在身份验证中,当用户使用其凭据成功登录时,将返回 JSON Web Token。==由于令牌是凭据,因此必须非常小心以防止安全问题。通常,令牌的保留时间不应超过所需时间。
==每当用户想要访问受保护的路由或资源时,用户都应发送 JWT,通常在使用持有者 架构的授权 请求头中发送,即Authorization
。==请求头的内容应如下所示:
Authorization: Bearer <token>
==在某些情况下,这可能是无状态授权机制。服务器的受保护路由将检查标头中的有效 JWT,如果存在,将允许用户访问受保护的资源。==如果 JWT 包含必要的数据,则可能会减少查询数据库以获取某些操作的需要,尽管情况可能并非总是如此。
5.整合JWT
引入对应依赖
说明:JDK8
只需要引入以下依赖就可以
< dependency>
< groupId> io.jsonwebtoken</ groupId>
< artifactId> jjwt</ artifactId>
< version> 0.9.1</ version>
</ dependency>
JDK8
以上的版本需要引入以下已离开
< dependency>
< groupId> io.jsonwebtoken</ groupId>
< artifactId> jjwt</ artifactId>
< version> 0.9.1</ version>
</ dependency>
< dependency>
< groupId> javax.xml.bind</ groupId>
< artifactId> jaxb-api</ artifactId>
< version> 2.3.1</ version>
</ dependency>
< dependency>
< groupId> com.sun.xml.bind</ groupId>
< artifactId> jaxb-impl</ artifactId>
< version> 2.3.3</ version>
</ dependency>
< dependency>
< groupId> com.sun.xml.bind</ groupId>
< artifactId> jaxb-core</ artifactId>
< version> 2.3.0</ version>
</ dependency>
定义JWT工具类,包括生成JWT和解析JWT
import io. jsonwebtoken. Claims ;
import io. jsonwebtoken. Jwts ;
import io. jsonwebtoken. SignatureAlgorithm ;
import javax. crypto. SecretKey ;
import javax. crypto. spec. SecretKeySpec ;
import java. util. Base64 ;
import java. util. Date ;
import java. util. UUID ;
public class JwtUtils {
public static final Long JWT_TTL = 60 * 60 * 1000L ;
public static final String JWT_KEY = "xha" ;
public static String getUUID ( ) {
String token = UUID . randomUUID ( ) . toString ( ) . replaceAll ( "-" , "" ) ;
return token;
}
public static String createJWT ( String subject) {
return getJwtBuilder ( subject, JwtUtils . JWT_TTL , getUUID ( ) ) ;
}
public static String createJWT ( String subject, Long ttlMillis) {
return getJwtBuilder ( subject, ttlMillis, getUUID ( ) ) ;
}
public static String createJWT ( String id, String subject, Long ttlMillis) {
return getJwtBuilder ( subject, ttlMillis, id) ;
}
private static String getJwtBuilder ( String subject, Long ttlMillis, String uuid) {
SecretKey secretKey = generalKey ( ) ;
long nowMillis = System . currentTimeMillis ( ) ;
Date now = new Date ( nowMillis) ;
long expMillis = nowMillis + ttlMillis;
Date expDate = new Date ( expMillis) ;
return Jwts . builder ( )
. setHeaderParam ( "typ" , "JWT" )
. setHeaderParam ( "alg" , "HS256" )
. setSubject ( subject)
. setId ( uuid)
. setIssuer ( "xha" )
. setIssuedAt ( now)
. setExpiration ( expDate)
. signWith ( SignatureAlgorithm . HS256 , secretKey)
. compact ( ) ;
}
public static SecretKey generalKey ( ) {
byte [ ] encodedKey = Base64 . getDecoder ( ) . decode ( JwtUtils . JWT_KEY ) ;
SecretKey key = new SecretKeySpec ( encodedKey, 0 , encodedKey. length, "AES" ) ;
return key;
}
public static Claims parseJWT ( String jwt) throws Exception {
SecretKey secretKey = generalKey ( ) ;
return Jwts . parser ( )
. setSigningKey ( secretKey)
. parseClaimsJws ( jwt)
. getBody ( ) ;
}
}
测试
public class TestJWT {
public static void main ( String [ ] args) {
String userId = "123456" ;
String jwt = JwtUtils . createJWT ( userId) ;
System . out. println ( jwt) ;
}
}
控制台输出JWT
使用JWT官网的JWT解析工具进行解析JSON Web Tokens - jwt.io
解析JWT
public static void main ( String [ ] args) {
String userId = "123456" ;
String jwt = JwtUtils . createJWT ( userId) ;
System . out. println ( jwt) ;
try {
Claims claims = JwtUtils . parseJWT ( jwt) ;
System . out. println ( claims) ;
} catch ( Exception e) {
throw new RuntimeException ( e) ;
}
}