5分钟详解JWT

本文介绍了如何在SpringBoot项目中集成JWT,并展示了创建和验证JWT令牌的步骤。通过添加spring-security-jwt依赖,创建测试类,对JWT的生成和解码过程进行了详细解释,包括头部信息、有效载荷和签名的组成。最后,提到了JWT在OAuth2授权中的应用场景,演示了如何在请求头中携带JWT进行授权验证。

 1、创建一个maven工程,引入jwt的springboot依赖

            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-jwt</artifactId>
                <version>1.0.10.RELEASE</version>
            </dependency>

2、创建一个测试类

public class JWTTest {
    String accessToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" +
            ".eyJhdWQiOlsicmVzMSJdLCJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiLCJST0xFX0FQSSJdLCJleHAiOjE2MjAzODQ5NjIsImF1dGhvcml0aWVzIjpbIlJPTEVfYWRtaW4iLCJ0ZXN0Il0sImp0aSI6ImY2MTk4MjBhLWIxOTItNDI4Yy05ZmFlLTg0YWMzMTI0NGZlMCIsImNsaWVudF9pZCI6InNwcmluZ2Nsb3Vkc2VjdXJpdHkifQ.lSpV6_0nFylzhdwTlqX_U4SkkcCRPn3tn5yAh12wyzU";

    String content ="{\"aud\":[\"res1\"],\"user_name\":\"admin\",\"scope\":[\"ROLE_ADMIN\",\"ROLE_USER\"," +
            "\"ROLE_API\"],\"exp\":1620384962,\"authorities\":[\"ROLE_admin\",\"test\"]," +
            "\"jti\":\"f619820a-b192-428c-9fae-84ac31244fe0\",\"client_id\":\"springcloudsecurity\"}";

    /**
     * 签名密钥
     */
    private final String signingKey = "jwtSigningKey";
    /**
     * 签名算法
     */
    private final Signer signer = new MacSigner(signingKey);
    /**
     * 认证密钥
     */
    private final String verifierKey = signingKey;
    /**
     * 认证算法
     */
    private final SignatureVerifier signatureVerifier = new MacSigner(verifierKey);

    @Test
    public void encode(){
        final Jwt encode = JwtHelper.encode(content,signer);
        System.out.println(encode.getEncoded());
        final String encodeJwt = encode.toString();
        System.out.println(encodeJwt);
        final Jwt decode = JwtHelper.decodeAndVerify(encode.getEncoded(), signatureVerifier);
        System.out.println(decode.toString());
        assert  encodeJwt.equals(decode.toString());
    }

    
    @Test
    public void decode(){
        final Jwt decode = JwtHelper.decode(accessToken);
        System.out.println(decode);
    }

}

3、运行一下结果:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsicmVzMSJdLCJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiLCJST0xFX0FQSSJdLCJleHAiOjE2MjAzODQ5NjIsImF1dGhvcml0aWVzIjpbIlJPTEVfYWRtaW4iLCJ0ZXN0Il0sImp0aSI6ImY2MTk4MjBhLWIxOTItNDI4Yy05ZmFlLTg0YWMzMTI0NGZlMCIsImNsaWVudF9pZCI6InNwcmluZ2Nsb3Vkc2VjdXJpdHkifQ.lSpV6_0nFylzhdwTlqX_U4SkkcCRPn3tn5yAh12wyzU
{"alg":"HS256","typ":"JWT"} {"aud":["res1"],"user_name":"admin","scope":["ROLE_ADMIN","ROLE_USER","ROLE_API"],"exp":1620384962,"authorities":["ROLE_admin","test"],"jti":"f619820a-b192-428c-9fae-84ac31244fe0","client_id":"springcloudsecurity"} [32 crypto bytes]
{"alg":"HS256","typ":"JWT"} {"aud":["res1"],"user_name":"admin","scope":["ROLE_ADMIN","ROLE_USER","ROLE_API"],"exp":1620384962,"authorities":["ROLE_admin","test"],"jti":"f619820a-b192-428c-9fae-84ac31244fe0","client_id":"springcloudsecurity"} [32 crypto bytes]

4、详解

jwt = 头部信息.有效信息.签名

jwt= eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsicmVzMSJdLCJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiLCJST0xFX0FQSSJdLCJleHAiOjE2MjAzODQ5NjIsImF1dGhvcml0aWVzIjpbIlJPTEVfYWRtaW4iLCJ0ZXN0Il0sImp0aSI6ImY2MTk4MjBhLWIxOTItNDI4Yy05ZmFlLTg0YWMzMTI0NGZlMCIsImNsaWVudF9pZCI6InNwcmluZ2Nsb3Vkc2VjdXJpdHkifQ.lSpV6_0nFylzhdwTlqX_U4SkkcCRPn3tn5yAh12wyzU

  • 头部信息,base64加密

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

{
  "alg": "HS256",
  "typ": "JWT"
}

jwt的头部承载两部分信息:

  1. 声明类型,这里是JWT
  2. 声明加密的算法 通常直接使用 HMACSHA256,也就是测试类中MacSigner使用的默认算法
  • 有效信息,base64加密

eyJhdWQiOlsicmVzMSJdLCJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiLCJST0xFX0FQSSJdLCJleHAiOjE2MjAzODQ5NjIsImF1dGhvcml0aWVzIjpbIlJPTEVfYWRtaW4iLCJ0ZXN0Il0sImp0aSI6ImY2MTk4MjBhLWIxOTItNDI4Yy05ZmFlLTg0YWMzMTI0NGZlMCIsImNsaWVudF9pZCI6InNwcmluZ2Nsb3Vkc2VjdXJpdHkifQ
包括:标注声明(选填)+公共声明+私有声明

  标准中注册的声明(都是选填)

{
	"aud": ["res1"],
	"exp": 1620384962,
	"jti": "f619820a-b192-428c-9fae-84ac31244fe0",
}
  • iss: jwt签发者
  • sub: jwt所面向的用户
  • aud: 接收jwt的一方
  • exp: jwt的过期时间,这个过期时间必须要大于签发时间
  • nbf: 定义在什么时间之前,该jwt都是不可用的.
  • iat: jwt的签发时间
  • jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

  公共的声明

  私有的声明

{    
    "user_name": "admin",
    "scope": ["ROLE_ADMIN", "ROLE_USER", "ROLE_API"],
    "authorities": ["ROLE_admin", "test"],
    "client_id": "springcloudsecurity"
}
  • 签名:HMACSHA256(头部信息 +"."+有效信息,secret)

lSpV6_0nFylzhdwTlqX_U4SkkcCRPn3tn5yAh12wyzU

5、在springboot oauth2中的应用

curl --location --request GET 'http://localhost:8080/' \
--header 'Authorization: Bearer eyJhdWQiOlsicmVzMSJdLCJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiLCJST0xFX0FQSSJdLCJleHAiOjE2MjAzODQ5NjIsImF1dGhvcml0aWVzIjpbIlJPTEVfYWRtaW4iLCJ0ZXN0Il0sImp0aSI6ImY2MTk4MjBhLWIxOTItNDI4Yy05ZmFlLTg0YWMzMTI0NGZlMCIsImNsaWVudF9pZCI6InNwcmluZ2Nsb3Vkc2VjdXJpdHkifQ'

在Header中加入Authorization头,写入jwt即可

### 什么是JSON Web Token (JWT) JSON Web Token(JWT)是一种开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间安全地传输信息。JWT使用JSON对象来表示数据,并支持通过加密或签名的方式确保信息的完整性和安全性[^1]。 JWT的核心设计理念是将用户认证信息直接嵌入到令牌中,而不是依赖于服务器端存储。这种方式使得JWT特别适合无状态认证系统,因为服务器不需要维护会话信息,从而提升了系统的可扩展性[^4]。 --- ### JWT的核心结构 JWT的结构由三部分组成,分别是Header(头部)、Payload(负载)和Signature(签名)。这三部分通过点号(`.`)连接,形成一个完整的JWT字符串。 #### 1. Header Header通常包含两部分信息:令牌类型(即JWT)和使用的签名算法(如HMAC SHA256或RSA)。例如: ```json { "alg": "HS256", "typ": "JWT" } ``` 这部分会被Base64编码后作为JWT的第一部分。 #### 2. Payload Payload是JWT的主要部分,包含了声明(Claims)。声明可以分为三种类型: - **Registered claims**(注册声明):预定义的标准字段,如`iss`(签发者)、`exp`(过期时间)、`sub`(主题)等。 - **Public claims**(公共声明):用户自定义的字段。 - **Private claims**(私有声明):应用内部使用的字段。 示例Payload: ```json { "sub": "1234567890", "name": "John Doe", "admin": true } ``` 同样,这部分会被Base64编码后作为JWT的第二部分。 #### 3. Signature 为了验证消息的来源并确保消息未被篡改,JWT需要对前两部分进行签名。签名过程如下: 1. 将Header和Payload进行Base64编码。 2. 使用指定的算法(如HMAC SHA256)和密钥对编码后的字符串进行签名。 签名公式为: ``` HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret) ``` 最终的JWT格式为: ``` <base64url-encoded-header>.<base64url-encoded-payload>.<signature> ``` --- ### JWT的工作原理 JWT的工作流程通常包括以下几个关键步骤: 1. **生成Token**:当用户登录成功后,服务器会根据用户的认证信息生成一个JWT,并将其返回给客户端。 2. **存储Token**:客户端可以将JWT存储在Cookie、LocalStorage或SessionStorage中。 3. **发送Token**:在后续请求中,客户端将JWT附加到HTTP请求头中(通常是`Authorization: Bearer <token>`)。 4. **验证Token**:服务器接收到请求后,解析JWT并验证其签名。如果签名有效,则允许访问受保护资源。 --- ### JWT的使用场景 JWT因其紧凑性和安全性,在以下场景中得到了广泛应用: 1. **身份认证**:JWT常用于Web应用中的用户认证。客户端在每次请求时携带JWT,服务器通过验证JWT确认用户身份[^2]。 2. **信息交换**:JWT可以在不同系统之间安全地传递信息,同时确保信息的完整性和真实性[^3]。 3. **分布式系统**:在微服务架构中,JWT可以用于跨服务的身份验证和授权。 4. **单点登录(SSO)**:JWT支持跨域认证,因此非常适合实现单点登录系统[^5]。 --- ### 示例代码:生成与解析JWT 以下是使用Python生成和解析JWT的示例代码: #### 生成JWT ```python import jwt import datetime secret_key = "my_secret_key" payload = { "sub": "1234567890", "name": "John Doe", "exp": datetime.datetime.utcnow() + datetime.timedelta(seconds=300) } token = jwt.encode(payload, secret_key, algorithm="HS256") print("Generated Token:", token) ``` #### 解析JWT ```python try: decoded_payload = jwt.decode(token, secret_key, algorithms=["HS256"]) print("Decoded Payload:", decoded_payload) except jwt.ExpiredSignatureError: print("Token has expired") except jwt.InvalidTokenError: print("Invalid token") ``` --- ### 注意事项 1. **安全性**:JWT本身并不提供加密功能,仅提供签名功能。如果需要加密,可以选择JWE(JSON Web Encryption)[^3]。 2. **Token过期管理**:应合理设置JWT的过期时间,并在必要时提供刷新机制。 3. **密钥管理**:签名密钥的安全性至关重要,必须妥善保管[^1]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宇哥哦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值