Avoid the pit Guide (a): Spring Security Oauth2 in refresh_token refresh access_token abnormal

problem

Spring Security Oauth2, when access_token is about to expire, you need to call / oauth / token, use refresh_token refresh access_token, this time there will be a pit:

That is if you are using Spring Security Framework default AuthenticationManager generated interface calls abnormal.

Specific information is given as follows:

No AuthenticationProvider found for org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken

analysis

To resolve this issue, read some of the source code and data and found clues that tokenServices.

Use the default tokenServices

The first is AuthorizationServerEndpointsConfigurer in the framework of creating a logical tokenServices.

If not specified tokenServices, then create a default tokenServices, namely DefaultTokenServices:

Specific create a default tokenServices logic:

Note that the default created tokenServices did not initialize authenticationManager, here is the key, the following will be used.

Secondly, DefaultTokenServices access_token refresh logic.

User authentication again on part of the logic is as follows:

As noted above, because there is no default tokenServices set authenticationManager, so it will not take this logic, there would be no re-authenticate the user.

tokenServices Custom

TokenServices custom logic is as follows:

@Bean
public DefaultTokenServices defaultTokenServices() throws Exception {    DefaultTokenServices defaultTokenServices = new DefaultTokenServices();    defaultTokenServices.setAuthenticationManager(this.authenticationManager);    defaultTokenServices.setTokenStore(jdbcTokenStore());    defaultTokenServices.setClientDetailsService(jdbcClientDetailsServiceBuilder());        // access token有效期2个小时    defaultTokenServices.setAccessTokenValiditySeconds(60 * 60 * 2);    // refresh token有效期30天    defaultTokenServices.setRefreshTokenValiditySeconds(60 * 60 * 24 * 30);    // 支持使用refresh token刷新access token    defaultTokenServices.setSupportRefreshToken(true);    // 允许重复使用refresh token    defaultTokenServices.setReuseRefreshToken(true);    return defaultTokenServices;}

The provision of the authenticationManager custom, and this time authentication mode is password, when so satisfied access_token refresh token for the user's secondary authentication conditions ( article have been described at the beginning ) , it will trigger a secondary user authentication.

此时,若采用Spring Security框架默认的authenticationManager,则必然会爆出文章开头处描述的问题。因为框架默认的authenticationManager只包含一个DaoAuthenticationProvider。

Spring Security Oauth2框架中,存在一个开发者实现好的能认证PreAuthenticatedAuthenticationToken的Provider:PreAuthenticatedAuthenticationProvider。

但是,Spring Security框架并没有在默认authenticationManager中初始化,所以,DefaultTokenServices在执行刷新方法时,在二次认证的地方便会报错。

知道了问题的根本,就容易解决,添加PreAuthenticatedAuthenticationProvider到authenticationManager中应该就可以完美解决了。

关于如何authenticationManager配置,方法多种多样,如覆盖掉Spring Security框架默认逻辑,或者完全自定义,都可以。本文不再赘述,后续也会出文章,详细阐述Spring Security如何配置,结合Spring Security Oauth2如何配置等等。

下面附上PreAuthenticatedAuthenticationProvider定义逻辑:


private PreAuthenticatedAuthenticationProvider preAuthenticatedAuthenticationProvider() {
    PreAuthenticatedAuthenticationProvider preAuthenticatedAuthenticationProvider = new PreAuthenticatedAuthenticationProvider();
    preAuthenticatedAuthenticationProvider.setPreAuthenticatedUserDetailsService(new UserDetailsByNameServiceWrapper(userDetailsService));
    return preAuthenticatedAuthenticationProvider;
}

 

不得不说,Spring Security框架确实非常复杂,设计真是巧夺天工,不得不佩服设计者和开发者,由衷的赞叹!

 

正文完!

 

本文系【银河架构师】原创,如需转载请在文章明显处注明作者及出处。

微信搜索【银河架构师】,发现更多精彩内容。

 

发布了29 篇原创文章 · 获赞 1 · 访问量 2217

Guess you like

Origin blog.csdn.net/liuminglei1987/article/details/103763106