Spring Security 自定义 AuthenticationProvider 验证方法调用了两次
Posted
技术标签:
【中文标题】Spring Security 自定义 AuthenticationProvider 验证方法调用了两次【英文标题】:Spring Security custom AuthenticationProvider authenticate method called twice 【发布时间】:2018-02-06 21:53:27 【问题描述】:我正在开发一个使用 API 密钥进行身份验证的 Spring Boot。我创建了一个自定义身份验证提供程序,并且身份验证方法被调用了两次。谁能告诉我为什么它被调用了两次?
这是我的身份验证方法:
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException
ApiAuthenticationToken authenticationToken = (ApiAuthenticationToken) authentication;
/**
* Authenticate the token
*/
ValidateApiKeyRequest request = new ValidateApiKeyRequest(authenticationToken.getApiKey());
ValidateApiKeyResp resp = getValidateApiKeyCommand().execute(request);
/**
* Populate and return a new authenticaiton token
*/
return createSuccessAuthentication(resp);
这是 createSuccessAuthentication 方法:
protected Authentication createSuccessAuthentication(final ValidateApiKeyResp resp)
List<GrantedAuthority> authorities = Lists.newArrayList();
authorities.add(new SimpleGrantedAuthority("API_KEY"));
return new ApiAuthenticationToken(resp.getApiKey(), authorities, true);
这是 ApiAuthenticationToken 构造函数:
public ApiAuthenticationToken(final ApiKey apiKey, Collection<? extends GrantedAuthority> authorities, boolean authenticated)
super(authorities);
setAuthenticated(true);
this.apiKey = apiKey;
这是我的安全配置:
protected void configure(HttpSecurity http) throws Exception
http.antMatcher(CONFIGURATION_MATCHER)
.exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint())
.and()
.addFilterBefore(apiKeyAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.csrf().disable()
.authorizeRequests().antMatchers(CONFIGURATION_MATCHER).authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authenticationProvider(apiKeyAuthenticationProvider());
【问题讨论】:
你是否碰巧在某处定义了 configure(AuthenticationManagerBuilder)? 不,我没有。我在类似的帖子上看到过这个答案,所以我知道这个问题。 还有其他建议吗? 您有重现该问题的小型示例项目吗? 【参考方案1】:以防万一其他人有这个问题:
问题与我的 spring 安全配置有关。我有几个用 @Bean 注释的方法 - 见下文
@Bean
public ApiKeyAuthenticationProvider apiKeyAuthenticationProvider()
return new ApiKeyAuthenticationProvider(getValidateApiKeyCommand());
@Bean
public RestAuthenticationEntryPoint restAuthenticationEntryPoint()
return new RestAuthenticationEntryPoint();
@Bean
public ApiKeyAuthenticationFilter apiKeyAuthenticationFilter() throws Exception
ApiKeyAuthenticationFilter apiKeyAuthenticationFilter = new ApiKeyAuthenticationFilter();
apiKeyAuthenticationFilter.setAuthenticationManager(authenticationManagerBean());
apiKeyAuthenticationFilter.setAuthenticationSuccessHandler(new ApiKeyAuthenticationSuccessHandler());
apiKeyAuthenticationFilter.setAuthenticationFailureHandler(new ApiKeyAuthenticationFailureHandler());
return apiKeyAuthenticationFilter;
但是这些 bean 在 configure(HttpSecurity http) 方法中再次注册。
protected void configure(HttpSecurity http) throws Exception
http.antMatcher(CONFIGURATION_MATCHER)
.exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint())
.and()
.addFilterBefore(apiKeyAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.csrf().disable()
.authorizeRequests().antMatchers(CONFIGURATION_MATCHER).authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authenticationProvider(apiKeyAuthenticationProvider());
解决方法是删除 @Bean 注释。现在看起来很明显:)
【讨论】:
以上是关于Spring Security 自定义 AuthenticationProvider 验证方法调用了两次的主要内容,如果未能解决你的问题,请参考以下文章
Spring Security入门(3-6)Spring Security 的鉴权 - 自定义权限前缀
Spring Security 之自定义UserDetails