Spring + Oauth2:如何刷新访问令牌

ddd*_*ddd 5 rest access-token oauth-2.0 spring-security-ldap spring-boot

我正在使用 Spring Boot 构建休息 Web 服务。身份验证是使用 Spring Security 和 OAuth2 实现的。用户通过 LDAP 服务器进行身份验证。这是我的 websecurityconfig

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    private RestAuthenticationSuccessHandler authenticationSuccessHandler;
    @Autowired
    private RestAuthenticationEntryPoint restAuthenticationEntryPoint;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http

            .httpBasic()
            .and()
            .csrf().disable()
            .sessionManagement().sessionCreationPolicy(
                    SessionCreationPolicy.STATELESS)
            .and()
            .exceptionHandling()
            .authenticationEntryPoint(restAuthenticationEntryPoint)
            .and()
            .authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/login").permitAll()
                .antMatchers("/logout").permitAll()
                .antMatchers("/ristore/**").authenticated()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .successHandler(authenticationSuccessHandler)
                .failureHandler(new SimpleUrlAuthenticationFailureHandler());
    }

    @Override  
    @Bean  
    public AuthenticationManager authenticationManagerBean() throws Exception {  
        return super.authenticationManagerBean();  
    }

    @Bean
    public RestAuthenticationSuccessHandler mySuccessHandler(){
        return new RestAuthenticationSuccessHandler();
    }
    @Bean
    public SimpleUrlAuthenticationFailureHandler myFailureHandler(){
        return new SimpleUrlAuthenticationFailureHandler();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        DefaultSpringSecurityContextSource contextSource = getSource();
        auth
        .ldapAuthentication()
            .userDnPatterns("cn={0},ou=institution,ou=people")
            .groupSearchBase("ou=groups")
            .contextSource(contextSource);
    }
 }
Run Code Online (Sandbox Code Playgroud)

附加配置在 authserverconfig 中完成,包括 clientdetailservice。

public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
     @Autowired
     @Qualifier("authenticationManagerBean")
     private AuthenticationManager authenticationManager;


     @Override
     public void configure(AuthorizationServerSecurityConfigurer oauthServer) 
       throws Exception {
         oauthServer.allowFormAuthenticationForClients();
     }

     @Override
     public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
          endpoints.tokenStore(new InMemoryTokenStore())
          .authenticationManager(authenticationManager);
     }
     @Override
     public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
          clients
            .inMemory()
            .withClient("ristoreclient")
            .scopes("read")
            .authorizedGrantTypes("password", "refresh_token", "client_credentials")
            .secret("ristoresecret")
            .accessTokenValiditySeconds(60);    
      }
 }
Run Code Online (Sandbox Code Playgroud)

它适用于初始登录。但是,当我尝试在旧令牌过期时使用刷新令牌获取新访问令牌时,出现错误“需要 UserDetailsS​​ervice”。在网上搜索答案后,我发现这个帖子有类似的问题:spring-security-oauth2 2.0.7 refresh token UserDetailsS​​ervice Configuration。基本上,那里的解决方案是创建一个自定义LdapUserDetailsService. 事情是它是在 xml 配置而不是 java 中设置的。此外,尚不清楚如何以及在何处注入此类。在另一种情况下, userdetailservice 实例被添加到身份验证服务器端点配置中。本文不提供该类的实现。

在我看来,拥有 userdetailservice 的想法是在发布新的访问令牌之前查找并查看此用户是否仍处于活动状态。矛盾的是,获取oauth2的refresh_token的请求只包含以下信息,不包含用户名/密码。

client_id=clientid
client_secret=clientsecret
refresh_token=1/6BMfW9j53gdGImsiyUH5kU5RsR4zwI9lUVX-tqf8JXQ&
grant_type=refresh_token
Run Code Online (Sandbox Code Playgroud)

Spring REST 的 OAuth2使用 Zuul 代理作为前端和 web api 之间的中间层来处理刷新令牌,这使得配置更加复杂。我应该如何在 Spring Boot 中为 oauth2 实现 userdetailsservice 以及应该在哪里注入它?