Spring Authorization Server JPA示例:如何用Builder设置clientSettings与tokenSettings
我在基于Spring Authorization Server的JPA实现自定义Client实体时,将clientSettings和tokenSettings设为String类型字段:
// Client entity @Column(length = 2000) private String clientSettings; @Column(length = 2000) private String tokenSettings;
目前创建Client实例时只能靠复制数据库中的JSON字符串赋值,写法繁琐且不优雅:
Client client = new Client(); client.setId(UUID.randomUUID().toString()); client.setClientIdIssuedAt(Instant.now()); client.setClientName("TTT"); client.setClientId("form-client"); client.setClientSecret("{noop}secret"); client.setRedirectUris( "http://127.0.0.1:4001/login/oauth2/code/felord-oidc,http://127.0.0.1:4001/authorized,http://127.0.0.1:4001/foo/bar,http://127.0.0.1:3001/api/auth/pinecone,https://spruce.jiahang.online/oauth_hcms,http://127.0.0.1:4001/foo/bart,http://36.135.4.69:4000/oauth_hcms,http://36.135.4.216:4000/oauth_hcms,http://localhost:3000/oauth_hcms,http://127.0.0.1:3000/oauth_hcms"); client.setClientAuthenticationMethods(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue()); client.setAuthorizationGrantTypes(AuthorizationGrantType.AUTHORIZATION_CODE.getValue() + "," + AuthorizationGrantType.REFRESH_TOKEN.getValue()); client.setScopes("openid,userinfo.read"); String clientSettingString = "{\"@class\":\"java.util.Collections$UnmodifiableMap\",\"settings.client.require-proof-key\":false,\"settings.client.require-authorization-consent\":true}"; String tokenSettingString = "{\"@class\":\"java.util.Collections$UnmodifiableMap\",\"settings.token.reuse-refresh-tokens\":true,\"settings.token.id-token-signature-algorithm\":[\"org.springframework.security.oauth2.jose.jws.SignatureAlgorithm\",\"RS256\"],\"settings.token.access-token-time-to-live\":[\"java.time.Duration\",300.000000000],\"settings.token.refresh-token-time-to-live\":[\"java.time.Duration\",3600.000000000]}"; client.setClientSettings(clientSettingString); client.setTokenSettings(tokenSettingString); clientRepo.save(client);
想知道是否可以用更优雅的Builder模式设置这两个属性,比如:
.tokenSettings(TokenSettings.builder().build()) .clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
解决方案
完全可以通过Builder模式实现优雅赋值,核心思路是利用Spring Authorization Server提供的ClientSettings.Builder和TokenSettings.Builder构建配置对象,再通过Jackson将其序列化为符合要求的JSON字符串。
步骤1:确保Jackson依赖存在
Spring Boot项目默认已包含Jackson相关依赖,无需额外引入;非Spring Boot项目需手动添加Jackson核心及模块依赖。
步骤2:封装序列化工具类
编写工具类统一处理配置对象到JSON字符串的转换:
import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.security.oauth2.server.authorization.settings.ClientSettings; import org.springframework.security.oauth2.server.authorization.settings.TokenSettings; public class ClientConfigSerializer { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); static { // 自动注册Java 8时间、JWS算法等必要模块 OBJECT_MAPPER.findAndRegisterModules(); } public static String serializeClientSettings(ClientSettings clientSettings) throws Exception { return OBJECT_MAPPER.writeValueAsString(clientSettings.getSettings()); } public static String serializeTokenSettings(TokenSettings tokenSettings) throws Exception { return OBJECT_MAPPER.writeValueAsString(tokenSettings.getSettings()); } }
步骤3:用Builder模式构建并赋值
现在可以用简洁的Builder方式设置属性:
Client client = new Client(); client.setId(UUID.randomUUID().toString()); client.setClientIdIssuedAt(Instant.now()); client.setClientName("TTT"); client.setClientId("form-client"); client.setClientSecret("{noop}secret"); client.setRedirectUris( "http://127.0.0.1:4001/login/oauth2/code/felord-oidc,http://127.0.0.1:4001/authorized,http://127.0.0.1:4001/foo/bar,http://127.0.0.1:3001/api/auth/pinecone,https://spruce.jiahang.online/oauth_hcms,http://127.0.0.1:4001/foo/bart,http://36.135.4.69:4000/oauth_hcms,http://36.135.4.216:4000/oauth_hcms,http://localhost:3000/oauth_hcms,http://127.0.0.1:3000/oauth_hcms"); client.setClientAuthenticationMethods(ClientAuthenticationMethod.CLIENT_SECRET_BASIC.getValue()); client.setAuthorizationGrantTypes(AuthorizationGrantType.AUTHORIZATION_CODE.getValue() + "," + AuthorizationGrantType.REFRESH_TOKEN.getValue()); client.setScopes("openid,userinfo.read"); // 构建ClientSettings并序列化 ClientSettings clientSettings = ClientSettings.builder() .requireAuthorizationConsent(true) .requireProofKey(false) .build(); client.setClientSettings(ClientConfigSerializer.serializeClientSettings(clientSettings)); // 构建TokenSettings并序列化 TokenSettings tokenSettings = TokenSettings.builder() .reuseRefreshTokens(true) .idTokenSignatureAlgorithm(SignatureAlgorithm.RS256) .accessTokenTimeToLive(Duration.ofSeconds(300)) .refreshTokenTimeToLive(Duration.ofSeconds(3600)) .build(); client.setTokenSettings(ClientConfigSerializer.serializeTokenSettings(tokenSettings)); clientRepo.save(client);
额外优化:在Client实体中添加便捷方法
在自定义Client实体类中添加重载setter,直接接收ClientSettings和TokenSettings对象,内部自动完成序列化:
// Client entity @Column(length = 2000) private String clientSettings; @Column(length = 2000) private String tokenSettings; public void setClientSettings(ClientSettings clientSettings) throws Exception { this.clientSettings = ClientConfigSerializer.serializeClientSettings(clientSettings); } public void setTokenSettings(TokenSettings tokenSettings) throws Exception { this.tokenSettings = ClientConfigSerializer.serializeTokenSettings(tokenSettings); }
之后使用时代码会更简洁:
client.setClientSettings(ClientSettings.builder() .requireAuthorizationConsent(true) .requireProofKey(false) .build()); client.setTokenSettings(TokenSettings.builder() .reuseRefreshTokens(true) .idTokenSignatureAlgorithm(SignatureAlgorithm.RS256) .accessTokenTimeToLive(Duration.ofSeconds(300)) .refreshTokenTimeToLive(Duration.ofSeconds(3600)) .build());
内容的提问来源于stack exchange,提问作者hezf
相关产品推荐
相关产品推荐

