| # 头部:包含令牌的类型(JWT) 与加密的签名算法((如 SHA256 或 ES256) ,Base64编码后加入第一部分 |
| # 有效载荷:通俗一点讲就是token中需要携带的信息都将存于此部分,比如:用户id、权限标识等信息。 |
| 注:该部分信息任何人都可以读出来,所以添加的信息需要加密才会保证信息的安全性 |
| # 签名:用于防止 JWT 内容被篡改, 会将头部和有效载荷分别进行 Base64编码,编码后用 . 连接组成新的字符串,然后再使用头部声明的签名算法进行签名。在具有秘钥的情况下,可以验证JWT的准确性,是否被篡改 |
| |
| http://localhost:8090/auth/oauth/authorize?client_id=mengxuegu-pc&response_type=code |






| # server子模块中的TokenConfig中配置如下 |
| public static final String SIGNING_KEY = "mengxeugu-key"; |
| @Bean |
| public JwtAccessTokenConverter jwtAccessTokenConverter() { |
| JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); |
| |
| converter.setSigningKey(SIGNING_KEY); |
| return converter; |
| } |
| @Bean |
| public TokenStore tokenStore() { |
| |
| |
| |
| return new JwtTokenStore(jwtAccessTokenConverter()); |
| } |
| |
| # server子模块中的AuthorizationServerConfig中配置如下 |
| @Autowired |
| private JwtAccessTokenConverter jwtAccessTokenConverter; |
| @Override |
| public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { |
| |
| |
| endpoints.tokenStore(tokenStore).accessTokenConverter(jwtAccessTokenConverter); |
| } |
-
启动认证服务器和资源服务器测试
-
使用密码模式获取一个token

-
检查该令牌

-
资源服务器对称解密jwt令牌
| # resource子模块中配置TokenConfig |
| @Configuration |
| public class TokenConfig { |
| public static final String SIGNING_KEY = "mengxeugu-key"; |
| @Bean |
| public JwtAccessTokenConverter jwtAccessTokenConverter() { |
| JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); |
| |
| converter.setSigningKey(SIGNING_KEY); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| return converter; |
| } |
| @Bean |
| public TokenStore tokenStore() { |
| |
| return new JwtTokenStore(jwtAccessTokenConverter()); |
| } |
| } |
| |
| # ResourceServerConfig中配置如下 |
| # 删除如下 |
| public ResourceServerTokenServices tokenService(){ |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| .tokenServices(tokenService()) |
| |
| # 添加如下 |
| @Autowired |
| private TokenStore tokenStore; |
| |
| .tokenStore(tokenStore) |
| |
| |
| |
| |
| keytool -genkeypair -alias oauth2 -keyalg RSA -keypass oauth2 -keystore oauth2.jks |
| -storepass oauth2 |
| |
| |
| |
| |
| |
| |
| |
| |
| |

| # 将oauth2.jks剪切到认证服务器子模块的resource目录下 |
| |
| # TokenConfig中配置如下 |
| KeyStoreKeyFactory factory = new KeyStoreKeyFactory( |
| new ClassPathResource("oauth2.jks"), "oauth2".toCharArray()); |
| converter.setKeyPair(factory.getKeyPair("oauth2")); |
| |
| # 删除如下 |
| converter.setSigningKey(SIGNING_KEY); |
| keytool |
| -genkeypair -alias oauth2 # 设置别名oauth2 |
| -keyalg RSA -keypass oauth2 # 设置keypass为oauth2 |
| -keystore oauth2.jks # 设置生成的文件名oauth2.jks |
| -storepass oauth2 |
| |
| KeyStoreKeyFactory factory = new KeyStoreKeyFactory( |
| new ClassPathResource("oauth2.jks"), # 加载oauth2.jks文件 |
| "oauth2".toCharArray()); # 使用之前设置的keypass |
| converter.setKeyPair(factory.getKeyPair("oauth2")); # 使用之前设置的别名 |
-
测试:启动认证服务器和资源服务器

-
资源服务器非对称解密jwt令牌
| # 进入网站http://slproweb.com/products/Win32OpenSSL.html下载openssl |

| # 下载openssl后双击直接安装 |
| # 配置环境变量:Path = C:\Program Files\OpenSSL-Win64\bin |
| # 将之前生成oauth2.jks发到c盘根目录下,以管理员的身份进入C:\Program Files\Java\jdk-11.0.13\bin目录执行如下命令生成公钥 |
| C:\Program Files\Java\jdk-11.0.13\bin>keytool -list -rfc |
| 输入密钥库口令: oauth2 |
| |
| MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArws0jvq7ciIW1ea7IZwm |
| kk4CxWKTk0R9hwZO1hEQA5+9hDs+mBBfYpw6kYETLtgGtDm8ayLnbMoq6sTkOELN |
| 1nYj1fIqffQCKKzBiiTMa9VDndLnATHIZpCOHnzqOPZBFg5TrQV0xMyWU9FT8qRB |
| GsntUdeI21tk/cN6rmVnDEGkFJmpT7JO+MlDMN6wAeANUUk+gZql/ZX8Hzn+xZrv |
| qYZ3HLCKFpRFbp/+b39d7VS8CwjP5Q1GtJKrVMAJ/Vm6GaQKtvsGDjkGj1E+lfDV |
| szbnK/p6R7B9ynXUvEDXkEjAnzTjJLL05MJdYbS3Osd7cSAcHB8pzHXD5WbpYWeJ |
| JQIDAQAB |
| |
| |
| MIIDQzCCAiugAwIBAgIEK51NDzANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJj |
| bjELMAkGA1UECBMCd3oxCzAJBgNVBAcTAmJqMQwwCgYDVQQKEwNteGcxDDAKBgNV |
| BAsTA214ZzENMAsGA1UEAxMEbWVuZzAeFw0yMjA0MDQwMjE0MDJaFw0yMjA3MDMw |
| MjE0MDJaMFIxCzAJBgNVBAYTAmNuMQswCQYDVQQIEwJ3ejELMAkGA1UEBxMCYmox |
| DDAKBgNVBAoTA214ZzEMMAoGA1UECxMDbXhnMQ0wCwYDVQQDEwRtZW5nMIIBIjAN |
| BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArws0jvq7ciIW1ea7IZwmkk4CxWKT |
| k0R9hwZO1hEQA5+9hDs+mBBfYpw6kYETLtgGtDm8ayLnbMoq6sTkOELN1nYj1fIq |
| ffQCKKzBiiTMa9VDndLnATHIZpCOHnzqOPZBFg5TrQV0xMyWU9FT8qRBGsntUdeI |
| 21tk/cN6rmVnDEGkFJmpT7JO+MlDMN6wAeANUUk+gZql/ZX8Hzn+xZrvqYZ3HLCK |
| FpRFbp/+b39d7VS8CwjP5Q1GtJKrVMAJ/Vm6GaQKtvsGDjkGj1E+lfDVszbnK/p6 |
| R7B9ynXUvEDXkEjAnzTjJLL05MJdYbS3Osd7cSAcHB8pzHXD5WbpYWeJJQIDAQAB |
| oyEwHzAdBgNVHQ4EFgQUA7Y9cGQZshEWO/WaGLtdxRkP1wcwDQYJKoZIhvcNAQEL |
| BQADggEBAD7ZCX02zuHcjaaod0UH2cKc7z2eCZl35IshGbEpJQ1TiQ4Rl9I4mDh+ |
| kQjLEeMbAD9LM2N/0kpSfBPvc0b2qFuU8hLqmfDWC2TAF1st9EGx+i+b1m9sXaDl |
| 2QgSvyt5KE81NxlnS5PpLDuFl2Bv/8RD4KSmdzM2zF+EFuYr1ZxNEoi5JIKxFcjF |
| JRYQSzLLL9sCLO5B+YXuobY7UW42oi0guWvVFuzkSrsEZb3gyZjbkWOXFXUPZCIK |
| H83FJWe0JytXziUhwdrwIDaTo4Q4mSJfYTRyKDKnwrGq0aWN3OTOzWtQpNu/9HLk |
| Wv5Gx47xMdHHHwffUliFSB24HvqVuG8= |
| |
- 在资源服务器的resource目录下新建public.txt
| -----BEGIN PUBLIC KEY----- |
| MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArws0jvq7ciIW1ea7IZwm |
| kk4CxWKTk0R9hwZO1hEQA5+9hDs+mBBfYpw6kYETLtgGtDm8ayLnbMoq6sTkOELN |
| 1nYj1fIqffQCKKzBiiTMa9VDndLnATHIZpCOHnzqOPZBFg5TrQV0xMyWU9FT8qRB |
| GsntUdeI21tk/cN6rmVnDEGkFJmpT7JO+MlDMN6wAeANUUk+gZql/ZX8Hzn+xZrv |
| qYZ3HLCKFpRFbp/+b39d7VS8CwjP5Q1GtJKrVMAJ/Vm6GaQKtvsGDjkGj1E+lfDV |
| szbnK/p6R7B9ynXUvEDXkEjAnzTjJLL05MJdYbS3Osd7cSAcHB8pzHXD5WbpYWeJ |
| JQIDAQAB |
| -----END PUBLIC KEY----- |
| # resource子模块TokenConfig配置如下 |
| # 删除如下: |
| converter.setSigningKey(SIGNING_KEY); |
| # 添加如下: |
| ClassPathResource resource = new ClassPathResource("public.txt"); |
| String publicKey = null; |
| try { |
| publicKey = IOUtils.toString(resource.getInputStream(), "UTF-8"); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } |
| converter.setVerifierKey(publicKey); |
- 测试


【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构