JSON Web Token (JWT): 理解与应用

news/2024/9/18 19:57:13/ 标签: json, 前端, 状态模式, JWT, token

JWT(JSON Web Token)是一种开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间以JSON对象的形式安全地传输信息。JWT通常用于身份验证和授权目的,因为它可以使用JSON对象在各方之间安全地传输信息

官网地址:https://jwt.io/

0.介绍

通俗地说,JWT的本质就是一个字符串,它是将用户信息保存到一个Json字符串中,然后进行编码后得到一个JWT token并且这个JWT token带有签名信息,接收后可以校验是否被篡改,所以可以用于在各方之间安全地将信息作为Json对象传输。

JWT_12">0.1.JWT的应用场景

身份验证 : 当用户成功登录时,服务器会生成一个JWT并将其发送给客户端。客户端在后续请求中将JWT附加到HTTP请求头中,以此来证明用户的身份。

授权 : JWT中可以包含用户的权限信息,这样服务器可以根据这些信息决定用户是否被允许访问某些资源。

信息传递 : 除了用户的身份和权限外,JWT还可以用来携带其他有用的信息,如用户的偏好设置等。

在 java 中 常与 Spring Security 框架配合使用

JWT的认证流程如下:

  1. 首先,前端通过Web表单将自己的用户名和密码发送到后端的接口,这个过程一般是一个POST请求。建议的方式是通过SSL加密的传输(HTTPS),从而避免敏感信息被嗅探
  2. 后端核对用户名和密码成功后,将包含用户信息的数据作为JWT的Payload,将其与JWT Header分别进行Base64编码拼接后签名,形成一个JWT Token,形成的JWT Token就是一个如同lll.zzz.xxx的字符串
  3. 后端将JWT Token字符串作为登录成功的结果返回给前端前端可以将返回的结果保存在浏览器中,退出登录时删除保存的JWT Token即可
  4. 前端在每次请求时将JWT Token放入HTTP请求头中的Authorization属性中(解决XSS和XSRF问题)
  5. 后端检查前端传过来的JWT Token,验证其有效性,比如检查签名是否正确、是否过期、token的接收方是否是自己等等
  6. 验证通过后,后端解析出JWT Token中包含的用户信息,进行其他逻辑操作(一般是根据用户信息得到权限等),返回结果

在这里插入图片描述

0.2.优点

这种基于token的认证方式相比传统的session认证方式更节约服务器资源,并且对移动端和分布式更加友好。其优点如下:

  • 支持跨域访问:cookie是无法跨域的,而token由于没有用到cookie(前提是将token放到请求头中),所以跨域后不会存在信息丢失问题

  • 无状态token机制在服务端不需要存储session信息,因为token自身包含了所有登录用户的信息,所以可以减轻服务端压力

  • 更适用CDN:可以通过内容分发网络请求服务端的所有资料

  • 更适用于移动端:当客户端是非浏览器平台时,cookie是不被支持的,此时采用token认证方式会简单很多

  • 无需考虑CSRF:由于不再依赖cookie,所以采用token认证方式不会发生CSRF,所以也就无需考虑CSRF的防御

JWT_59">1.JWT的结构

JWT是一种自包含的令牌格式。JWT由三个部分组成:头部、载荷和签名。

在这里插入图片描述

1.1.头部 (Header)

头部通常包含两个部分:

  • typ: 表示该令牌的类型,通常是“JWT”。
  • alg: 指定签名算法,例如 HMAC SHA-256 或 RSA。

头部通常以JSON格式书写,并经过Base64Url编码。

1.2.载荷 (Payload)

载荷包含了需要作为声明传输的信息。这些声明可以分为三类:

  • 标准声明:由JWT规范定义的声明。
    • iss (issuer): 发行者。
    • sub (subject): 主题,通常是指用户ID。
    • aud (audience): 接收者,即令牌的预期受众。
    • exp (expiration time): 过期时间。
    • nbf (not before): 该时间之前不可使用。
    • iat (issued at): 发行时间。
    • jti (JWT ID): 一个唯一的标识符,用于防止重放攻击。
  • 私有声明:由发行者和接收者约定的声明,例如用户的角色或权限等。
  • 公共声明:虽然不是JWT规范的一部分,但可以在任何JWT中使用。

载荷也是经过Base64Url编码的。

1.3.签名 (Signature)

签名部分保证了JWT的完整性和安全性。签名通过将头部和载荷进行编码并使用指定的算法(如HMAC SHA-256 RSA或ECDSA)进行计算得到。签名确保了:

  • 令牌没有被篡改。
  • 令牌是由可信的一方发行的。

签名部分同样经过Base64Url编码。

1.4.JWS, JWK

JWS ,也就是JWT Signature,其结构就是在之前nonsecure JWT的基础上,在头部声明签名算法,并在最后添加上签名。创建签名,是保证jwt不能被他人随意篡改。我们通常使用的JWT一般都是JWS

为了完成签名,除了用到header信息和payload信息外,还需要算法的密钥,也就是secretKey。

加密的算法一般有2类:

  • 对称加密:secretKey指加密密钥,可以生成签名与验签
  • 非对称加密:secretKey指私钥,只用来生成签名,不能用来验签(验签用的是公钥)

JWT的密钥或者密钥对,一般统一称为JSON Web Key,也就是JWK

到目前为止,jwt的签名算法有三种:

  • HMAC【哈希消息验证码(对称)】:HS256/HS384/HS512
  • RSASSA【RSA签名算法(非对称)】 :(RS256/RS384/RS512)
  • ECDSA【椭圆曲线数据签名算法(非对称)】 :(ES256/ES384/ES512)

2.实现与工具

JWT_126">2.1.jjwt (Java JWT)

GitHub 仓库地址:https://github.com/jwtk/jjwt

这是一个基于Java的库,用于在JVM和Android平台上创建和验证JSON Web Tokens (JWTs)和JSON Web Keys (JWKs)。

它支持多种JOSE工作组的RFC规范:

  • RFC 7519: JSON Web Token (JWT)
  • RFC 7515: JSON Web Signature (JWS)
  • RFC 7516: JSON Web Encryption (JWE)
  • 等等
2.1.1.导入Maven依赖
token tag">token tag">token punctuation"><dependencytoken punctuation">>token tag">token tag">token punctuation"><groupIdtoken punctuation">>io.jsonwebtokentoken tag">token tag">token punctuation"></groupIdtoken punctuation">>token tag">token tag">token punctuation"><artifactIdtoken punctuation">>jjwt-apitoken tag">token tag">token punctuation"></artifactIdtoken punctuation">>token tag">token tag">token punctuation"><versiontoken punctuation">>0.11.5token tag">token tag">token punctuation"></versiontoken punctuation">>
token tag">token tag">token punctuation"></dependencytoken punctuation">>
token tag">token tag">token punctuation"><dependencytoken punctuation">>token tag">token tag">token punctuation"><groupIdtoken punctuation">>io.jsonwebtokentoken tag">token tag">token punctuation"></groupIdtoken punctuation">>token tag">token tag">token punctuation"><artifactIdtoken punctuation">>jjwt-impltoken tag">token tag">token punctuation"></artifactIdtoken punctuation">>token tag">token tag">token punctuation"><versiontoken punctuation">>0.11.5token tag">token tag">token punctuation"></versiontoken punctuation">>
token tag">token tag">token punctuation"></dependencytoken punctuation">>
token tag">token tag">token punctuation"><dependencytoken punctuation">>token tag">token tag">token punctuation"><groupIdtoken punctuation">>io.jsonwebtokentoken tag">token tag">token punctuation"></groupIdtoken punctuation">>token tag">token tag">token punctuation"><artifactIdtoken punctuation">>jjwt-jacksontoken tag">token tag">token punctuation"></artifactIdtoken punctuation">>token tag">token tag">token punctuation"><versiontoken punctuation">>0.11.5token tag">token tag">token punctuation"></versiontoken punctuation">>
token tag">token tag">token punctuation"></dependencytoken punctuation">>
2.1.2.测试代码
token keyword">import token import">token namespace">iotoken punctuation">.jsonwebtokentoken punctuation">.token class-name">Claimstoken punctuation">;
token keyword">import token import">token namespace">iotoken punctuation">.jsonwebtokentoken punctuation">.token class-name">Jwtstoken punctuation">;
token keyword">import token import">token namespace">iotoken punctuation">.jsonwebtokentoken punctuation">.token class-name">SignatureAlgorithmtoken punctuation">;
token keyword">import token import">token namespace">iotoken punctuation">.jsonwebtokentoken punctuation">.securitytoken punctuation">.token class-name">Keystoken punctuation">;
token keyword">import token import">token namespace">orgtoken punctuation">.springframeworktoken punctuation">.webtoken punctuation">.bindtoken punctuation">.annotationtoken punctuation">.token class-name">RequestMappingtoken punctuation">;
token keyword">import token import">token namespace">orgtoken punctuation">.springframeworktoken punctuation">.webtoken punctuation">.bindtoken punctuation">.annotationtoken punctuation">.token class-name">RestControllertoken punctuation">;token keyword">import token import">token namespace">javatoken punctuation">.securitytoken punctuation">.token class-name">Keytoken punctuation">;
token keyword">import token import">token namespace">javatoken punctuation">.utiltoken punctuation">.token class-name">Datetoken punctuation">;
token keyword">import token import">token namespace">javatoken punctuation">.utiltoken punctuation">.token class-name">UUIDtoken punctuation">;token annotation punctuation">@RestController
token keyword">public token keyword">class token class-name">JwtController token punctuation">{token comment">// 密钥 : 实际开发时 应该从 配置文件 / 持久化存储中 获取token keyword">private token class-name">String secrettoken punctuation">;token comment">// token时效:24小时token keyword">public token keyword">static token keyword">final token keyword">long token constant">EXPIRE token operator">= token number">1000 token operator">* token number">60 token operator">* token number">60 token operator">* token number">24token punctuation">;token annotation punctuation">@RequestMappingtoken punctuation">(token string">"/create"token punctuation">)token keyword">public token class-name">String token function">createTokentoken punctuation">(token punctuation">)token punctuation">{token comment">// 生成一个随机的密钥 IDtoken class-name">String keyId token operator">= token constant">UUIDtoken punctuation">.token function">randomUUIDtoken punctuation">(token punctuation">)token punctuation">.token function">toStringtoken punctuation">(token punctuation">)token punctuation">;token comment">// 密钥secret token operator">= keyIdtoken punctuation">;token comment">// 创建一个 JWT 令牌token class-name">String jwt token operator">= token class-name">Jwtstoken punctuation">.token function">buildertoken punctuation">(token punctuation">)token comment">// 设置JWT头部参数,指定令牌类型为JWTtoken punctuation">.token function">setHeaderParamtoken punctuation">(token string">"typ"token punctuation">, token string">"JWT"token punctuation">)token comment">// 设置JWT头部参数,指定签名算法为HS256token punctuation">.token function">setHeaderParamtoken punctuation">(token string">"alg"token punctuation">, token string">"HS256"token punctuation">)token comment">// 设置JWT过期时间,当前时间戳加上设定的过期时长token punctuation">.token function">setExpirationtoken punctuation">(token keyword">new token class-name">Datetoken punctuation">(token class-name">Systemtoken punctuation">.token function">currentTimeMillistoken punctuation">(token punctuation">) token operator">+ token constant">EXPIREtoken punctuation">)token punctuation">)token comment">// 设置主题,通常是用户身份标识token punctuation">.token function">setSubjecttoken punctuation">(token string">"admin"token punctuation">)token comment">// 添加角色声明token punctuation">.token function">claimtoken punctuation">(token string">"role"token punctuation">, token string">"admin"token punctuation">)token comment">// 设置用户ID为1token punctuation">.token function">claimtoken punctuation">(token string">"id"token punctuation">, token number">1token punctuation">)token comment">// 设置用户昵称为"王小二"token punctuation">.token function">claimtoken punctuation">(token string">"nickname"token punctuation">, token string">"王小二"token punctuation">)token comment">// 设置令牌签发时间token punctuation">.token function">setIssuedAttoken punctuation">(token keyword">new token class-name">Datetoken punctuation">(token punctuation">)token punctuation">)token comment">// 设置唯一标识符token punctuation">.token function">setIdtoken punctuation">( keyId token punctuation">)token comment">// 使用HS256算法和密钥签名token punctuation">.token function">signWithtoken punctuation">(token class-name">SignatureAlgorithmtoken punctuation">.token constant">HS256token punctuation">, secrettoken punctuation">.token function">getBytestoken punctuation">(token punctuation">)token punctuation">)token comment">// 将令牌压缩为紧凑形式的字符串token punctuation">.token function">compacttoken punctuation">(token punctuation">)token punctuation">;token keyword">return jwttoken punctuation">;token punctuation">}token annotation punctuation">@RequestMappingtoken punctuation">(token string">"/check"token punctuation">)token keyword">public  token keyword">void token function">checkTokentoken punctuation">(token class-name">String jwttoken punctuation">) token punctuation">{token class-name">Systemtoken punctuation">.outtoken punctuation">.token function">printlntoken punctuation">(token string">"jwt = " token operator">+ jwttoken punctuation">)token punctuation">;token comment">// 创建一个安全的密钥token class-name">Key secureKey token operator">= token class-name">Keystoken punctuation">.token function">hmacShaKeyFortoken punctuation">(secrettoken punctuation">.token function">getBytestoken punctuation">(token punctuation">)token punctuation">)token punctuation">;token keyword">try token punctuation">{token comment">// 使用Jwts.parserBuilder()方法构建一个解析器,该解析器使用secureKey作为签名密钥token comment">// 然后使用这个解析器解析jwt字符串,获取到Claims对象,即JWT的主体部分token class-name">Claims claims token operator">= token class-name">Jwtstoken punctuation">.token function">parserBuildertoken punctuation">(token punctuation">)token punctuation">.token function">setSigningKeytoken punctuation">(secureKeytoken punctuation">)token punctuation">.token function">buildtoken punctuation">(token punctuation">)token punctuation">.token function">parseClaimsJwstoken punctuation">(jwttoken punctuation">)token punctuation">.token function">getBodytoken punctuation">(token punctuation">)token punctuation">;token comment">// 打印解析后的 JWT 信息token class-name">Systemtoken punctuation">.outtoken punctuation">.token function">printlntoken punctuation">(token string">"Subject: " token operator">+ claimstoken punctuation">.token function">getSubjecttoken punctuation">(token punctuation">)token punctuation">)token punctuation">;token class-name">Systemtoken punctuation">.outtoken punctuation">.token function">printlntoken punctuation">(token string">"Role: " token operator">+ claimstoken punctuation">.token function">gettoken punctuation">(token string">"role"token punctuation">, token class-name">Stringtoken punctuation">.token keyword">classtoken punctuation">)token punctuation">)token punctuation">;token class-name">Systemtoken punctuation">.outtoken punctuation">.token function">printlntoken punctuation">(token string">"Issue Time: " token operator">+ claimstoken punctuation">.token function">getIssuedAttoken punctuation">(token punctuation">)token punctuation">)token punctuation">;token class-name">Systemtoken punctuation">.outtoken punctuation">.token function">printlntoken punctuation">(token string">"JWT ID: " token operator">+ claimstoken punctuation">.token function">getIdtoken punctuation">(token punctuation">)token punctuation">)token punctuation">;token class-name">Systemtoken punctuation">.outtoken punctuation">.token function">printlntoken punctuation">(token string">"user nickname: " token operator">+ claimstoken punctuation">.token function">gettoken punctuation">(token string">"nickname"token punctuation">)token punctuation">)token punctuation">;token comment">// 可以在这里添加更多逻辑来验证 JWT 的有效性,例如检查过期时间等token keyword">iftoken punctuation">(claimstoken punctuation">.token function">getExpirationtoken punctuation">(token punctuation">)token operator">==token keyword">nulltoken punctuation">)token punctuation">{token class-name">Systemtoken punctuation">.outtoken punctuation">.token function">printlntoken punctuation">(token string">"过期时间不能为空 Expiration time cannot be null"token punctuation">)token punctuation">;token punctuation">}token punctuation">} token keyword">catch token punctuation">(token class-name">Exception etoken punctuation">) token punctuation">{token comment">// 如果 JWT 无法验证,这里会捕获异常token class-name">Systemtoken punctuation">.errtoken punctuation">.token function">printlntoken punctuation">(token string">"Invalid JWT: " token operator">+ etoken punctuation">.token function">getMessagetoken punctuation">(token punctuation">)token punctuation">)token punctuation">;token punctuation">}token punctuation">}
token punctuation">}

2.2.Nimbus

Nimbus JOSE + JWT 是一个非常强大的 Java 库,用于处理 JSON Web Signature (JWS), JSON Web Encryption (JWE), JSON Web Key (JWK), JSON Web Token (JWT) 和 OAuth 2.0 授权服务器。这个库是由 NimbusDS 开发的,并且广泛应用于身份验证和授权系统中。

2.2.1.导入依赖

首先,您需要在 Maven 项目中添加 json-jwt 的依赖:

        token tag">token tag">token punctuation"><dependencytoken punctuation">>token tag">token tag">token punctuation"><groupIdtoken punctuation">>com.nimbusdstoken tag">token tag">token punctuation"></groupIdtoken punctuation">>token tag">token tag">token punctuation"><artifactIdtoken punctuation">>nimbus-jose-jwttoken tag">token tag">token punctuation"></artifactIdtoken punctuation">>token tag">token tag">token punctuation"><versiontoken punctuation">>9.40token tag">token tag">token punctuation"></versiontoken punctuation">>token tag">token tag">token punctuation"></dependencytoken punctuation">>
2.2.2.测试代码

token keyword">import token import">token namespace">comtoken punctuation">.nimbusdstoken punctuation">.josetoken punctuation">.token class-name">JOSEExceptiontoken punctuation">;
token keyword">import token import">token namespace">comtoken punctuation">.nimbusdstoken punctuation">.josetoken punctuation">.token class-name">JWSAlgorithmtoken punctuation">;
token keyword">import token import">token namespace">comtoken punctuation">.nimbusdstoken punctuation">.josetoken punctuation">.token class-name">JWSHeadertoken punctuation">;
token keyword">import token import">token namespace">comtoken punctuation">.nimbusdstoken punctuation">.josetoken punctuation">.cryptotoken punctuation">.token class-name">MACSignertoken punctuation">;
token keyword">import token import">token namespace">comtoken punctuation">.nimbusdstoken punctuation">.josetoken punctuation">.cryptotoken punctuation">.token class-name">MACVerifiertoken punctuation">;
token keyword">import token import">token namespace">comtoken punctuation">.nimbusdstoken punctuation">.jwttoken punctuation">.token class-name">JWTClaimsSettoken punctuation">;
token keyword">import token import">token namespace">comtoken punctuation">.nimbusdstoken punctuation">.jwttoken punctuation">.token class-name">SignedJWTtoken punctuation">;
token keyword">import token import">token namespace">orgtoken punctuation">.springframeworktoken punctuation">.webtoken punctuation">.bindtoken punctuation">.annotationtoken punctuation">.token class-name">RequestMappingtoken punctuation">;
token keyword">import token import">token namespace">orgtoken punctuation">.springframeworktoken punctuation">.webtoken punctuation">.bindtoken punctuation">.annotationtoken punctuation">.token class-name">RestControllertoken punctuation">;token keyword">import token import">token namespace">javatoken punctuation">.texttoken punctuation">.token class-name">ParseExceptiontoken punctuation">;
token keyword">import token import">token namespace">javatoken punctuation">.utiltoken punctuation">.token class-name">Datetoken punctuation">;
token keyword">import token import">token namespace">javatoken punctuation">.utiltoken punctuation">.token class-name">UUIDtoken punctuation">;token annotation punctuation">@RestController
token keyword">public token keyword">class token class-name">JwtController token punctuation">{token comment">// 密钥 : 实际开发时 应该从 配置文件 / 持久化存储中 获取token keyword">private token class-name">String secrettoken punctuation">;token annotation punctuation">@RequestMappingtoken punctuation">(token string">"/create"token punctuation">)token keyword">public token class-name">String token function">createTokentoken punctuation">(token punctuation">) token punctuation">{token keyword">try token punctuation">{token comment">// 生成一个随机的密钥 IDtoken class-name">String keyId token operator">= token constant">UUIDtoken punctuation">.token function">randomUUIDtoken punctuation">(token punctuation">)token punctuation">.token function">toStringtoken punctuation">(token punctuation">)token punctuation">;token comment">// 密钥secret token operator">= keyIdtoken punctuation">;token comment">// 创建一个 HMAC 签名器token class-name">MACSigner signer token operator">= token keyword">new token class-name">MACSignertoken punctuation">(secrettoken punctuation">.token function">getBytestoken punctuation">(token punctuation">)token punctuation">)token punctuation">;token comment">// 设置 JWT 的声明token class-name">JWTClaimsSettoken punctuation">.Builder builder token operator">= token keyword">new token class-name">JWTClaimsSettoken punctuation">.Buildertoken punctuation">(token punctuation">)token punctuation">;buildertoken punctuation">.token function">subjecttoken punctuation">(token string">"admin"token punctuation">)token punctuation">;buildertoken punctuation">.token function">claimtoken punctuation">(token string">"role"token punctuation">, token string">"admin"token punctuation">)token punctuation">;buildertoken punctuation">.token function">issueTimetoken punctuation">(token keyword">new token class-name">Datetoken punctuation">(token punctuation">)token punctuation">)token punctuation">;buildertoken punctuation">.token function">jwtIDtoken punctuation">(keyIdtoken punctuation">)token punctuation">;token comment">// 构建 JWT Claims Settoken class-name">JWTClaimsSet claimsSet token operator">= buildertoken punctuation">.token function">buildtoken punctuation">(token punctuation">)token punctuation">;token comment">// 创建一个空的 SignedJWT 对象token class-name">SignedJWT signedJWT token operator">= token keyword">new token class-name">SignedJWTtoken punctuation">(token keyword">new token class-name">JWSHeadertoken punctuation">(token class-name">JWSAlgorithmtoken punctuation">.token constant">HS256token punctuation">)token punctuation">,claimsSettoken punctuation">)token punctuation">;token comment">// 签名 JWTsignedJWTtoken punctuation">.token function">signtoken punctuation">(signertoken punctuation">)token punctuation">;token comment">// 将 JWT 转换为紧凑形式token class-name">String jwt token operator">= signedJWTtoken punctuation">.token function">serializetoken punctuation">(token punctuation">)token punctuation">;token keyword">return jwttoken punctuation">;token punctuation">} token keyword">catch token punctuation">(token class-name">JOSEException etoken punctuation">) token punctuation">{etoken punctuation">.token function">printStackTracetoken punctuation">(token punctuation">)token punctuation">;token punctuation">}token keyword">return token keyword">nulltoken punctuation">;token punctuation">}token annotation punctuation">@RequestMappingtoken punctuation">(token string">"/check"token punctuation">)token keyword">public token keyword">void token function">checkTokentoken punctuation">(token class-name">String jwttoken punctuation">) token punctuation">{token keyword">try token punctuation">{token class-name">Systemtoken punctuation">.outtoken punctuation">.token function">printlntoken punctuation">(token string">"jwt = " token operator">+ jwttoken punctuation">)token punctuation">;token comment">// 解析 JWTtoken class-name">SignedJWT signedJWT token operator">= token class-name">SignedJWTtoken punctuation">.token function">parsetoken punctuation">(jwttoken punctuation">)token punctuation">;token comment">// 验证 JWTtoken class-name">MACVerifier verifier token operator">= token keyword">new token class-name">MACVerifiertoken punctuation">( secrettoken punctuation">.token function">getBytestoken punctuation">(token punctuation">) token punctuation">)token punctuation">;token keyword">boolean isValid token operator">= signedJWTtoken punctuation">.token function">verifytoken punctuation">(verifiertoken punctuation">)token punctuation">;token keyword">if token punctuation">(token operator">!isValidtoken punctuation">) token punctuation">{token class-name">Systemtoken punctuation">.outtoken punctuation">.token function">printlntoken punctuation">(token string">"无效的 JWT 签名 Invalid JWT signature."token punctuation">)token punctuation">;token keyword">returntoken punctuation">;token punctuation">}token comment">// 获取 JWT Claimstoken class-name">JWTClaimsSet claimsSet token operator">= signedJWTtoken punctuation">.token function">getJWTClaimsSettoken punctuation">(token punctuation">)token punctuation">;token class-name">Systemtoken punctuation">.outtoken punctuation">.token function">printlntoken punctuation">(token string">"Subject: " token operator">+ claimsSettoken punctuation">.token function">getSubjecttoken punctuation">(token punctuation">)token punctuation">)token punctuation">;token class-name">Systemtoken punctuation">.outtoken punctuation">.token function">printlntoken punctuation">(token string">"Role: " token operator">+ claimsSettoken punctuation">.token function">getStringClaimtoken punctuation">(token string">"role"token punctuation">)token punctuation">)token punctuation">;token class-name">Systemtoken punctuation">.outtoken punctuation">.token function">printlntoken punctuation">(token string">"Issue Time: " token operator">+ claimsSettoken punctuation">.token function">getIssueTimetoken punctuation">(token punctuation">)token punctuation">)token punctuation">;token class-name">Systemtoken punctuation">.outtoken punctuation">.token function">printlntoken punctuation">(token string">"JWT ID: " token operator">+ claimsSettoken punctuation">.token function">getJWTIDtoken punctuation">(token punctuation">)token punctuation">)token punctuation">;token punctuation">} token keyword">catch token punctuation">(token class-name">JOSEException token operator">| token class-name">ParseException etoken punctuation">) token punctuation">{etoken punctuation">.token function">printStackTracetoken punctuation">(token punctuation">)token punctuation">;token punctuation">}token punctuation">}token comment">/*** token 通过 header传递* 再通过 request 取出*/token annotation punctuation">@RequestMappingtoken punctuation">(token string">"/checkHeader"token punctuation">)token keyword">public token keyword">void token function">checkHeaderTokentoken punctuation">(token class-name">HttpServletRequest requesttoken punctuation">) token punctuation">{token keyword">try token punctuation">{token class-name">String jwt token operator">= requesttoken punctuation">.token function">getHeadertoken punctuation">(token string">"Authorization"token punctuation">)token punctuation">;token class-name">Systemtoken punctuation">.outtoken punctuation">.token function">printlntoken punctuation">(token string">"jwt header=> " token operator">+ jwttoken punctuation">)token punctuation">;token comment">// 解析 JWTtoken class-name">SignedJWT signedJWT token operator">= token class-name">SignedJWTtoken punctuation">.token function">parsetoken punctuation">(jwttoken punctuation">)token punctuation">;token comment">// 验证 JWTtoken class-name">MACVerifier verifier token operator">= token keyword">new token class-name">MACVerifiertoken punctuation">( secrettoken punctuation">.token function">getBytestoken punctuation">(token punctuation">) token punctuation">)token punctuation">;token keyword">boolean isValid token operator">= signedJWTtoken punctuation">.token function">verifytoken punctuation">(verifiertoken punctuation">)token punctuation">;token keyword">if token punctuation">(token operator">!isValidtoken punctuation">) token punctuation">{token class-name">Systemtoken punctuation">.outtoken punctuation">.token function">printlntoken punctuation">(token string">"无效的 JWT 签名 Invalid JWT signature."token punctuation">)token punctuation">;token keyword">returntoken punctuation">;token punctuation">}token comment">// 获取 JWT Claimstoken class-name">JWTClaimsSet claimsSet token operator">= signedJWTtoken punctuation">.token function">getJWTClaimsSettoken punctuation">(token punctuation">)token punctuation">;token class-name">Systemtoken punctuation">.outtoken punctuation">.token function">printlntoken punctuation">(token string">"Subject: " token operator">+ claimsSettoken punctuation">.token function">getSubjecttoken punctuation">(token punctuation">)token punctuation">)token punctuation">;token class-name">Systemtoken punctuation">.outtoken punctuation">.token function">printlntoken punctuation">(token string">"Role: " token operator">+ claimsSettoken punctuation">.token function">getStringClaimtoken punctuation">(token string">"role"token punctuation">)token punctuation">)token punctuation">;token class-name">Systemtoken punctuation">.outtoken punctuation">.token function">printlntoken punctuation">(token string">"Issue Time: " token operator">+ claimsSettoken punctuation">.token function">getIssueTimetoken punctuation">(token punctuation">)token punctuation">)token punctuation">;token class-name">Systemtoken punctuation">.outtoken punctuation">.token function">printlntoken punctuation">(token string">"JWT ID: " token operator">+ claimsSettoken punctuation">.token function">getJWTIDtoken punctuation">(token punctuation">)token punctuation">)token punctuation">;token punctuation">} token keyword">catch token punctuation">(token class-name">JOSEException token operator">| token class-name">ParseException etoken punctuation">) token punctuation">{etoken punctuation">.token function">printStackTracetoken punctuation">(token punctuation">)token punctuation">;token punctuation">}token punctuation">}
token punctuation">}
2.2.3.请求测试
###
GET http://localhost:8080/create

生成token : eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsInJvbGUiOiJhZG1pbiIsImV4cCI6MTcyMzQ1MDgyOCwiaWF0IjoxNzIzMzY0NDI4LCJqdGkiOiI5Yzc3N2YwZC03NDU5LTQ3MTUtYmVkNy1mNWViYzJiNmMwOTgifQ.Y_P7L4gehl0kJwxTnwUxX8Yy502qrCHQ0hkxod58ly8

###
GET http://localhost:8080/check?jwt=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsInJvbGUiOiJhZG1pbiIsImV4cCI6MTcyMzQ1MDgyOCwiaWF0IjoxNzIzMzY0NDI4LCJqdGkiOiI5Yzc3N2YwZC03NDU5LTQ3MTUtYmVkNy1mNWViYzJiNmMwOTgifQ.Y_P7L4gehl0kJwxTnwUxX8Yy502qrCHQ0hkxod58ly8

idea 控制台:
Subject: admin
Role: admin
Issue Time: Sun Aug 11 16:20:28 CST 2024
JWT ID: 9c777f0d-7459-4715-bed7-f5ebc2b6c098

###
GET http://localhost:8080/checkHeader
Content-Type: application/json
Authorization: eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsInJvbGUiOiJhZG1pbiIsImV4cCI6MTcyMzQ1MDgyOCwiaWF0IjoxNzIzMzY0NDI4LCJqdGkiOiI5Yzc3N2YwZC03NDU5LTQ3MTUtYmVkNy1mNWViYzJiNmMwOTgifQ.Y_P7L4gehl0kJwxTnwUxX8Yy502qrCHQ0hkxod58ly8

idea 控制台:
Subject: admin
Role: admin
Issue Time: Sun Aug 11 16:20:28 CST 2024
JWT ID: 9c777f0d-7459-4715-bed7-f5ebc2b6c098


http://www.ppmy.cn/news/1511594.html

相关文章

更改Docker默认存储位置

Docker镜像和容器等数据默认保存在目录/var/lib/docker目录下&#xff0c;我们可以更改Docker 的默认存储位置&#xff0c;比如改到数据盘。需注决&#xff0c;变更存储位置时&#xff0c;原来的镜像和容器有可能丢失。 1、确认docker默认存放目录 [rootkfk12 ~]# docker inf…

Linux平台Display Server与Desktop Environment

Display Driver Linux中的显示服务器&#xff08;Display Server&#xff09;是什么&#xff1f; 显示服务器是一个应用程序&#xff0c;其主要任务是协调客户端与其他操作系统&#xff0c;硬件以及彼此之间的输入和输出。显示服务器通过显示服务器协议与其客户端进行通信。 …

<数据集>骑行头盔识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;5026张 标注数量(xml文件个数)&#xff1a;5026 标注数量(txt文件个数)&#xff1a;5026 标注类别数&#xff1a;3 标注类别名称&#xff1a;[helmet, without_helmet, two_wheeler] 序号类别名称图片数框数1helm…

在Matlab中进行射频电路S、Z、Y、ABCD等参数的转换

在Matlab中进行射频电路S、Z、Y、ABCD等参数的转换 目录 在Matlab中进行射频电路S、Z、Y、ABCD等参数的转换1、转换案例-3dB电桥2、将转换结果应用到ADS中制造理想3dB电桥器件 在微带线的ABCD矩阵的推导、转换与级联-Matlab计算实例&#xff08;S、Z、Y参数转换&#xff09;中&…

SpringBoot开启多端口探究--开启gRPC端口

文章目录 前情提要一、gRPC的特别之处二、粗暴方案原始的GrpcObservabilityServer集成支持方案评价 三、改进方案基本原理改造结果 四、小结 前情提要 之前咱们聊过SpringBoot下开启多端口有3个思路&#xff0c;并分析了第一种开启独立management端口的实现细节&#xff0c;今…

【深度学习】【语音TTS】GPT-SoVITS v2 实战,训练一个人的音色,Docker镜像

文章目录 原理Dockerdocker push训练教程: https://www.yuque.com/baicaigongchang1145haoyuangong/ib3g1e/xyyqrfwiu3e2bgyk 原理 Docker 不用docker不行,不好分配显卡, 做个docker镜像: docker pull pytorch/pytorch:2.1.2

【AI趋势6】大模型与游戏共振

大语言模型与游戏环境的相结合&#xff0c;正在为AI Agent训练打造最佳训练场。游戏不仅能为AI Agent训练提与现实世界类似的虚拟环境&#xff0c;还能为AI Agent训练提供清晰、可量化的评估规则&#xff0c;大幅提升技术迭代与测试效率。当前&#xff0c;包括OpenAI、DeepMind…

前端面试题-什么是JavaScript的闭包?有哪些应用场景?

定义: 一个函数能够访问其它函数内部定义的变量 形成的原理: (1)函数创建&#xff1a;在一个函数&#xff08;外部函数&#xff09;中定义另一个函数&#xff08;内部函数&#xff09;。 (2)内部函数访问&#xff1a;内部函数可以访问和修改外部函数中的局部变量。 (3)函数…

Spring Cloud Eureka快速搭建:微服务注册中心的配置步骤

Spring Cloud Eureka快速搭建&#xff1a;微服务注册中心的配置步骤 目录 引言Spring Cloud微服务架构概述什么是Eureka&#xff1f;Eureka Server的搭建步骤 4.1 创建Eureka Server项目4.2 配置Eureka Server4.3 启动Eureka Server4.4 多实例Eureka Server的搭建 Eureka Cli…

无人机电池充电器技术详解

随着无人机技术的飞速发展&#xff0c;其作为航拍、物流、农业、监测等多领域的重要工具&#xff0c;对电池续航能力和充电效率提出了更高要求。无人机电池充电器作为保障无人机长时间运行的关键设备&#xff0c;其技术水平的提升直接影响到无人机的使用效率和安全性。本文将从…

牛客网习题——通过C++实现

一、目标 实现下面4道练习题增强C代码能力。 1.求123...n_牛客题霸_牛客网 (nowcoder.com) 2.计算日期到天数转换_牛客题霸_牛客网 (nowcoder.com) 3.日期差值_牛客题霸_牛客网 (nowcoder.com) 4.打印日期_牛客题霸_牛客网 (nowcoder.com) 二、对目标的实现 1.求123...n_…

【Solidity】基础介绍

数据类型 值类型 值类型的变量在赋值或作为函数参数传递时会被复制。 布尔类型&#xff1a;bool整数类型&#xff1a; 无符号&#xff1a;uint8、uint16、…、uint256 (uint256 可简写为 uint)有符号&#xff1a;int8、int16、…、int256 (int256可简写为 int) 地址类型&…

Unity的物理系统

目录 3D 物理系统 主要组件 2D 物理系统 主要组件 物理引擎的选择与应用 物理模拟的控制与优化 Unity中Nvidia PhysX引擎与Box2D引擎在性能和功能上的具体比较是什么&#xff1f; 如何在Unity项目中实现Havok物理引擎&#xff0c;并与PhysX或Box2D引擎结合使用&#xf…

像素尺寸物理尺寸分辨率

同样尺寸的图片&#xff08;如448448像素&#xff09;的确会有相同的像素数量&#xff0c;但分辨率的概念不仅仅取决于像素数&#xff0c;还包括图像在物理世界中的显示或打印尺寸。因此&#xff0c;像素尺寸相同的图片在不同的物理尺寸下显示时&#xff0c;分辨率可以不同。 …

UE5.4 用自带OpenCV4.55读取png、MP4、摄像头并在ui中显示的方法

创建c项目&#xff0c;项目build.cs中开启模块&#xff1a; // Copyright Epic Games, Inc. All Rights Reserved.using UnrealBuildTool;public class OpencvT : ModuleRules {public OpencvT(ReadOnlyTargetRules Target) : base(Target){PCHUsage PCHUsageMode.UseExplici…

Kali Linux 命令大全

一、引言 Kali Linux 作为一款专为渗透测试和安全研究设计的操作系统&#xff0c;拥有丰富的命令行工具&#xff0c;熟练掌握这些命令对于高效地进行安全测试和分析至关重要。本文将为您详细介绍 Kali Linux 中常用的命令&#xff0c;涵盖系统信息获取、文件操作、网络分析、用…

Vue3 组件命名

最简单的方式 无须引入插件&#xff0c;可直接命名&#xff08;缺点&#xff0c;可能就是丑了&#xff09; // 组件命名 defineOptions({name: Menu}) 优雅的命名方式 安装 vite-plugin-vue-setup-extend 插件 npm i vite-plugin-vue-setup-extend -D vite-plugin-vue-se…

分布式数据库在传统车联网厂商的应用实践 | OceanBase案例

本文作者&#xff1a;慧视通科技&#xff0c;梁君 传统车联网厂商运维百亿级数据的痛点与难点 深圳慧视通科技&#xff08;简称慧视通&#xff09;作为专业的位置数据综合运营服务提供商&#xff0c;一直深耕智能交通领域&#xff0c;依托车联网、云计算、大数据处理、无线通信…

Go语言 类封装和绑定方法

本篇文章主要内容为Go语言类相关操作&#xff1a;封装和绑定方法介绍及示例。 目录 封装 绑定方法 类方法形参 指针形参 设置类方法参数 指针与非指针区别 总结 封装 go语言支持类的操作&#xff0c;但是没有class关键字&#xff0c;使用struct来模拟类。 示例如下&am…

Java - File、IO流

File类 File是java.io.包下的类&#xff0c;File类的对象&#xff0c;用于代表当前操作系统的文件&#xff08;可以是文件、文件夹&#xff09; File类只能对文件本身进行操作&#xff0c;不能读写文件里面存储的数据。 创建File类的对象&#xff1a; //创建file对象//1.具体…