You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Authorization Server JPA示例:如何用Builder设置clientSettings与tokenSettings

问题:Spring Authorization Server中优雅设置Client的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 04:05:12