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

自定义JdbcOAuth2AuthorizationService导致sid缺失及刷新令牌报错

问题描述

我正在按照入门指南搭建Spring Authorization Server(依赖为org.springframework.boot:spring-boot-starter-oauth2-authorization-server:3.1.2),但当我定义如下OAuth2AuthorizationService Bean时:

@Bean
public OAuth2AuthorizationService authorizationService(JdbcOperations jdbcOperations,
    RegisteredClientRepository registeredClientRepository) {
  return new JdbcOAuth2AuthorizationService(jdbcOperations,
      registeredClientRepository);
}

生成的id_token中缺少SessionId声明“sid”,导致使用刷新令牌获取新令牌时服务器抛出如下错误:

java.lang.IllegalArgumentException: value cannot be null
        at org.springframework.util.Assert.notNull(Assert.java:204) ~[spring-core-6.0.10.jar:6.0.10]
        at org.springframework.security.oauth2.jwt.JwtClaimsSet$Builder.claim(JwtClaimsSet.java:167) ~[spring-security-oauth2-jose-6.1.1.jar:6.1.1]
        at org.springframework.security.oauth2.server.authorization.token.JwtGenerator.generate(JwtGenerator.java:137) ~[spring-security-oauth2-authorization-server-1.1.1.jar:1.1.1]
        at org.springframework.security.oauth2.server.authorization.token.JwtGenerator.generate(JwtGenerator.java:60) ~[spring-security-oauth2-authorization-server-1.1.1.jar:1.1.1]
        at org.springframework.security.oauth2.server.authorization.token.DelegatingOAuth2TokenGenerator.generate(DelegatingOAuth2TokenGenerator.java:59) ~[spring-security-oauth2-authorization-server-1.1.1.jar:1.1.1]

移除该Bean后,令牌中的“sid”声明能正确设置。我使用JdbcOAuth2AuthorizationService将授权信息存储到数据库以实现授权服务器的水平扩展,请问是否遗漏了什么配置?


问题原因与解决方案

问题出在自定义JdbcOAuth2AuthorizationService时,未完整配置配套的持久化组件,导致会话ID(sid)无法被正确持久化和读取。默认的内存实现会自动维护会话关联信息,但切换到JDBC存储后需要手动补充相关配置:

  • 步骤1:确保数据库表结构正确
    Spring Authorization Server的JDBC实现依赖特定的数据库表,需提前创建:

    • oauth2_authorization:存储授权会话、令牌等核心信息,其中包含会话ID相关字段
    • oauth2_authorization_consent:存储用户对客户端的授权同意记录

    这些表的结构需符合官方定义的规范,确保字段完整才能正常存储sid。

  • 步骤2:注册配套的JdbcOAuth2AuthorizationConsentService
    仅注册授权服务的JDBC实现是不完整的,需要同时注册授权同意服务的JDBC实现,保证授权数据的完整链路:

    @Bean
    public OAuth2AuthorizationConsentService authorizationConsentService(JdbcOperations jdbcOperations,
        RegisteredClientRepository registeredClientRepository) {
      return new JdbcOAuth2AuthorizationConsentService(jdbcOperations, registeredClientRepository);
    }
    
  • 步骤3:在授权服务器安全链中关联自定义授权服务
    配置SecurityFilterChain时,需明确将自定义的OAuth2AuthorizationService绑定到授权服务器配置中:

    @Bean
    @Order(1)
    public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http,
        OAuth2AuthorizationService authorizationService) throws Exception {
      OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
      http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
          .authorizationService(authorizationService); // 关联自定义授权服务
      return http.build();
    }
    
  • 步骤4:自定义JwtGenerator确保sid声明被添加
    如果上述配置后仍存在sid缺失问题,可以自定义JwtGenerator,手动从授权信息中提取sid并添加到JWT声明:

    @Bean
    public JwtGenerator jwtGenerator(JwtEncoder jwtEncoder,
        OAuth2AuthorizationService authorizationService) {
      JwtGenerator jwtGenerator = new JwtGenerator(jwtEncoder);
      jwtGenerator.setJwtClaimsSetCustomizer((context) -> {
        OAuth2Authorization authorization = context.getAuthorization();
        String sid = authorization.getAttribute(OAuth2AuthorizationAttributeNames.SESSION_ID);
        if (sid != null) {
          context.getClaims().claim("sid", sid);
        }
      });
      return jwtGenerator;
    }
    

内容的提问来源于stack exchange,提问作者DarkImage

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 08:35:59