Spring Security 6:如何重写令牌验证逻辑适配非标准OIDC提供商?
Spring Security 6 适配GET类型的令牌验证URL
针对你的场景,Spring Security默认的令牌 introspection(验证)逻辑遵循标准POST请求规范,要适配GET类型的验证接口,核心是自定义OpaqueTokenIntrospector实现,替换掉默认的实现类。
步骤1:实现自定义的令牌验证器
创建一个类实现OpaqueTokenIntrospector接口,在introspect方法里发送GET请求到你的验证URL,解析响应并封装成OAuth2AuthenticatedPrincipal对象。
示例代码(用RestTemplate实现):
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal; import org.springframework.security.oauth2.server.resource.introspection.DefaultOAuth2AuthenticatedPrincipal; import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector; import org.springframework.web.client.RestTemplate; import java.util.Map; public class GetBasedTokenIntrospector implements OpaqueTokenIntrospector { private final String introspectionUri; private final RestTemplate restTemplate; // 如果验证接口需要客户端认证(比如Basic Auth),可在这里注入客户端ID和密钥并配置认证 public GetBasedTokenIntrospector(String introspectionUri) { this.introspectionUri = introspectionUri; this.restTemplate = new RestTemplate(); // 若需Basic Auth,添加拦截器: // restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor(clientId, clientSecret)); } @Override public OAuth2AuthenticatedPrincipal introspect(String token) { // 构建带access_token参数的GET请求URL String url = String.format("%s?access_token=%s", this.introspectionUri, token); // 发送GET请求获取令牌信息 Map<String, Object> tokenAttributes = restTemplate.getForObject(url, Map.class); // 验证令牌有效性(根据提供商返回的active字段判断) if (tokenAttributes == null || !Boolean.TRUE.equals(tokenAttributes.get("active"))) { throw new IllegalArgumentException("Invalid token"); } // 将返回属性封装成OAuth2AuthenticatedPrincipal返回 return new DefaultOAuth2AuthenticatedPrincipal( (String) tokenAttributes.get("username"), tokenAttributes, null // 权限信息,根据实际返回字段调整 ); } }
步骤2:在Spring Security配置中替换默认验证器
在SecurityFilterChain配置里,指定使用自定义的OpaqueTokenIntrospector:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.SecurityFilterChain; @Configuration public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .oauth2ResourceServer(oauth2 -> oauth2 .opaqueToken(token -> token .introspector(new GetBasedTokenIntrospector("https://xxxxx.domain/oauth2/rest/token/info")) ) ); return http.build(); } }
关键注意事项
- 如果验证接口需要客户端身份认证,记得在RestTemplate或WebClient中配置对应的认证逻辑(比如Basic Auth拦截器)。
- 解析响应时,要根据提供商实际返回的字段调整,比如用户名字段可能不是
username,权限信息可能在其他字段中,需对应修改DefaultOAuth2AuthenticatedPrincipal的构造参数。 - 可添加异常处理逻辑,捕获请求超时、HTTP错误等情况,转换成Spring Security标准异常(如
OAuth2AuthenticationException)。
内容的提问来源于stack exchange,提问作者François Poirier
相关产品推荐
相关产品推荐

