Spring Boot资源服务器(5.7及更早版本)替换BearerTokenAuthentication方法
Spring Security 5.7及更早版本替换不透明令牌认证后的Authentication实例
在Spring Security 5.7及更早版本中,要将不透明令牌 introspection 生成的BearerTokenAuthentication替换为自定义Authentication实现,可通过以下两种方式实现:
方案一:自定义OpaqueTokenAuthenticationProvider
核心思路是重写默认的OpaqueTokenAuthenticationProvider,在认证流程的最后阶段替换生成的认证对象:
- 实现自定义Authentication类
先定义你的自定义认证对象,比如CustomAuthentication,需实现Authentication接口或继承AbstractAuthenticationToken:
public class CustomAuthentication extends AbstractAuthenticationToken { private final String token; private final Object principal; public CustomAuthentication(Object principal, Collection<? extends GrantedAuthority> authorities, String token) { super(authorities); this.principal = principal; this.token = token; setAuthenticated(true); } @Override public Object getCredentials() { return this.token; } @Override public Object getPrincipal() { return this.principal; } }
- 自定义OpaqueTokenAuthenticationProvider
继承默认的OpaqueTokenAuthenticationProvider,重写authenticate方法,在原认证逻辑完成后,将BearerTokenAuthentication转换为自定义的认证对象:
public class CustomOpaqueTokenAuthenticationProvider extends OpaqueTokenAuthenticationProvider { public CustomOpaqueTokenAuthenticationProvider(OpaqueTokenIntrospector introspector) { super(introspector); } @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { // 先执行默认的令牌校验与解析逻辑 Authentication defaultAuth = super.authenticate(authentication); if (defaultAuth instanceof BearerTokenAuthentication bearerAuth) { // 转换为自定义Authentication实例 return new CustomAuthentication( bearerAuth.getPrincipal(), bearerAuth.getAuthorities(), bearerAuth.getToken() ); } return defaultAuth; } }
- 配置SecurityFilterChain
在Spring Security配置中,替换默认的OpaqueTokenAuthenticationProvider为自定义实现:
@Configuration @EnableWebSecurity public class ResourceServerConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .oauth2ResourceServer(oauth2 -> oauth2 .opaqueToken(token -> token .authenticationProvider(customOpaqueTokenAuthenticationProvider()) ) ); return http.build(); } @Bean public CustomOpaqueTokenAuthenticationProvider customOpaqueTokenAuthenticationProvider() { // 这里可以使用默认的NimbusOpaqueTokenIntrospector,或者自定义的Introspector OpaqueTokenIntrospector introspector = new NimbusOpaqueTokenIntrospector( "https://your-auth-server/introspect", "your-client-id", "your-client-secret" ); return new CustomOpaqueTokenAuthenticationProvider(introspector); } }
方案二:通过AuthenticationPostProcessor处理
如果不想重写整个Provider,也可以通过在认证流程后添加一个AuthenticationPostProcessor,将BearerTokenAuthentication转换为自定义实例:
- 自定义AuthenticationPostProcessor
public class CustomAuthenticationPostProcessor implements AuthenticationPostProcessor { @Override public Authentication postProcess(Authentication authentication) { if (authentication instanceof BearerTokenAuthentication bearerAuth) { return new CustomAuthentication( bearerAuth.getPrincipal(), bearerAuth.getAuthorities(), bearerAuth.getToken() ); } return authentication; } }
- 配置到BearerTokenAuthenticationFilter
在Security配置中,获取BearerTokenAuthenticationFilter并设置自定义的AuthenticationPostProcessor:
@Configuration @EnableWebSecurity public class ResourceServerConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .oauth2ResourceServer(oauth2 -> oauth2.opaqueToken(Customizer.withDefaults())); // 获取BearerTokenAuthenticationFilter并设置PostProcessor http.addFilterAfter( new BearerTokenAuthenticationFilter( http.getSharedObject(AuthenticationManager.class), new BearerTokenAuthenticationConverter() ) { @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { Authentication customAuth = new CustomAuthenticationPostProcessor().postProcess(authResult); super.successfulAuthentication(request, response, chain, customAuth); } }, BearerTokenAuthenticationFilter.class ); return http.build(); } }
内容的提问来源于stack exchange,提问作者eztam
相关产品推荐
相关产品推荐

