如何基于新版Spring Authorization Server实现OAuth2 private_key_jwt授权(JWS、JWT Bearer)及相关实现示例咨询
嘿,我来帮你梳理下如何基于新版Spring Authorization Server实现private_key_jwt授权,同时给你一些可落地的示例参考~
一、基础依赖准备
首先确保你的项目引入了最新版的Spring Authorization Server依赖:
Maven 依赖
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-oauth2-authorization-server</artifactId> <version>1.2.3</version> <!-- 请使用最新稳定版本 --> </dependency>
Gradle 依赖
implementation 'org.springframework.security:spring-security-oauth2-authorization-server:1.2.3'
另外,客户端生成签名JWT需要用到Nimbus JOSE + JWT库,也需要引入:
<!-- Maven --> <dependency> <groupId>com.nimbusds</groupId> <artifactId>nimbus-jose-jwt</artifactId> <version>9.37.3</version> </dependency>
二、授权服务器配置
1. 注册支持private_key_jwt的客户端
创建RegisteredClient Bean,指定客户端的认证方式为PRIVATE_KEY_JWT,并配置客户端的JWKS端点(授权服务器会从这里获取公钥来验证JWT签名):
@Bean public RegisteredClientRepository registeredClientRepository() { RegisteredClient privateKeyJwtClient = RegisteredClient.withId(UUID.randomUUID().toString()) .clientId("private-key-jwt-demo-client") // 指定认证方式为private_key_jwt .clientAuthenticationMethod(ClientAuthenticationMethod.PRIVATE_KEY_JWT) // 根据业务需求选择授权类型,比如客户端凭证模式 .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) .scope("demo-api:read") // 客户端的JWKS端点,授权服务器会通过这里获取公钥验证签名 .jwkSetUri("http://localhost:8081/.well-known/jwks.json") .build(); return new InMemoryRegisteredClientRepository(privateKeyJwtClient); }
2. 授权服务器基础配置
配置AuthorizationServerSettings Bean,保持默认即可,它会启用JWT Bearer相关的认证逻辑:
@Bean public AuthorizationServerSettings authorizationServerSettings() { return AuthorizationServerSettings.builder().build(); }
三、客户端生成签名JWT(private_key_jwt凭证)
客户端需要生成一个用自身私钥签名的JWT作为认证凭证,下面是示例代码:
import com.nimbusds.jose.JWSAlgorithm; import com.nimbusds.jose.JWSHeader; import com.nimbusds.jose.JWSSigner; import com.nimbusds.jose.crypto.RSASSASigner; import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.interfaces.RSAPrivateKey; import java.util.Date; import java.util.UUID; public class PrivateKeyJwtGenerator { public static String generateClientAssertion(String clientId, String tokenEndpoint) throws Exception { // 生产环境请使用存储的私钥,这里仅为示例生成临时RSA密钥对 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(2048); KeyPair keyPair = keyPairGenerator.generateKeyPair(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 构建JWS头部,指定签名算法为RS256 JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.RS256) .keyID("client-demo-key-1") // 需要和JWKS中的kid一致 .build(); // 构建JWT声明 JWTClaimsSet claimsSet = new JWTClaimsSet.Builder() .subject(clientId) // 主体为客户端ID .issuer(clientId) // 签发者为客户端ID .audience(tokenEndpoint) // 受众为授权服务器的token端点 .expirationTime(new Date(System.currentTimeMillis() + 3600 * 1000)) // 1小时过期 .issueTime(new Date()) .jwtID(UUID.randomUUID().toString()) // 唯一标识 .build(); // 签名生成JWT SignedJWT signedJWT = new SignedJWT(header, claimsSet); JWSSigner signer = new RSASSASigner(privateKey); signedJWT.sign(signer); return signedJWT.serialize(); } }
四、测试private_key_jwt授权流程
用curl发送请求到授权服务器的token端点,携带生成的客户端JWT:
curl --location --request POST 'http://localhost:8080/oauth2/token' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'grant_type=client_credentials' \ --data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \ --data-urlencode 'client_assertion=<替换为你生成的JWT字符串>' \ --data-urlencode 'scope=demo-api:read'
如果配置正确,你会收到包含access_token的响应。
五、官方示例参考
虽然官方文档暂时没有详细的private_key_jwt实现说明,但Spring Authorization Server的官方代码仓库中包含了专门的private_key_jwt示例模块,涵盖了完整的客户端注册、JWKS服务搭建以及端到端的流程测试,你可以直接参考这个示例来完善自己的实现。
内容的提问来源于stack exchange,提问作者Wojciech Marusarz
相关产品推荐
相关产品推荐

