春季如何在oauth2中使用刷新令牌更新访问令牌?

时间:2019-02-04 09:26:44

标签: spring spring-boot spring-security oauth-2.0 spring-security-oauth2

我对Spring非常陌生,这是我第一次尝试使用oauth2进行Spring安全。我已经用弹簧安全性实现了OAuth2,并且确实获得了访问令牌和刷新令牌。但是,在发送刷新令牌以获取新的访问令牌时,我收到了“ o.s.s.o.provider.endpoint.TokenEndpoint-IllegalStateException,需要UserDetailsS​​ervice。”

其他用户对类似问题的解决方案似乎是将UserDetailsS​​ervice附加到端点。

所以我做了同样的事情,现在当我尝试使用Grant_type:refresh_token和refresh_token:THE TOKEN以及客户端ID和密码将请求发送到时,我得到一个找不到用户的错误。

请参考下面的WebSecurityConfiguration类:

@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter{

    @Autowired
    private UserDetailsService customUserDetailsService;

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

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(customUserDetailsService)
            .passwordEncoder(encoder());
    }

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

        http.csrf().disable()
        .antMatcher("/**")
        .authorizeRequests()
        .antMatchers("/login**")
        .permitAll()
        .anyRequest()
        .authenticated();
     }

    public PasswordEncoder encoder() {
        return NoOpPasswordEncoder.getInstance();
    }
}

请参考下面的AuthorizationServerConfiguration类:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private DataSource dataSource;

    @Autowired 
    private CustomUserDetailsService userDetailsService;

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.checkTokenAccess("isAuthenticated()");
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        clients.jdbc(dataSource);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

        endpoints.authenticationManager(authenticationManager)
            .tokenStore(tokenStore());
        .userDetailsService(userDetailsService);  
    }

    @Bean
    public TokenStore tokenStore() {
        return new JdbcTokenStore(dataSource);
    }

}

请参考下面的ResourceServerConfiguration类:

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter{


    @Autowired
    DataSource dataSource;

    @Bean
    public TokenStore tokenStore() { 
        return new JdbcTokenStore(dataSource);
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId("scout").tokenStore(tokenStore());
    }

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

        http
         .authorizeRequests (). antMatchers ("/oauth/token", "/oauth/authorize **").permitAll();  
         // .anyRequest (). authenticated (); 
         http.requestMatchers (). antMatchers ("/api/patients/**") // Deny access to "/ private"
         .and (). authorizeRequests ()
         .antMatchers ("/api/patients/**"). access ("hasRole ('PATIENT')") 
         .and (). requestMatchers (). antMatchers ("/api/doctors/**") // Deny access to "/ admin"
         .and (). authorizeRequests ()
         .antMatchers ("/api/doctors/**"). access ("hasRole ('DOCTOR')");
    }
}

CustomUserDetailsS​​ervice类(如果需要)以供参考:

@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private UsersRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {

        Optional<Users> usersOptional = userRepository.findByEmail(email);

        Users user = null;

        if(usersOptional.isPresent()) {
            System.out.println(usersOptional.isPresent());
            user = usersOptional.get();
        }else {
            throw new RuntimeException("Email is not registered!");
        }

        return new CustomUserDetails(user);
    }

}

我认为,服务器应仅检查刷新令牌的有效性,因为我们不会通过刷新令牌传递用户详细信息。所以我不知道为什么它首先需要userDetails。

如果我缺少什么,请帮助并指导! 预先感谢。

1 个答案:

答案 0 :(得分:1)

我不确定。但是正如我所见,WebSecurityConfiguration中的代码可以连接默认的InMemoryUserDetailsManager UserDetailsS​​ervice。这可能是您拥有2个不同提供程序的原因。在您撰写的一篇文章中,您从另一本书阅读了用户。请尝试更改您的代码,如下所示,并告诉我是否有帮助:

原是:

@Autowired
    private UserDetailsService customUserDetailsService;

我的愿景应该是:

@Autowired
   private CustomUserDetailsService customUserDetailsService;