从 Spring 引导版本 1.5.7 移动到 2.0 时出现 Oauth 2.0 错误,在 1.5 上工作正常。7.RELEASE

Oauth 2.0 error when moving from Spring boot version 1.5.7 to 2.0, was working fine on 1.5.7.RELEASE

我在 Spring Boot 1.5.7 中实现了 Oauth,但是当我切换到 2 时它显示错误 "java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"。

根据一些研究,我发现这可能是密码存储和密码编码的问题。

我尝试过的 - 我尝试在授权服务器文件中对客户端密码进行编码,但没有任何作用,错误仍然存​​在。

我也尝试用 {bcrypt} 作为前缀保存密码,因为 spring security 5 在密码搜索过程中寻找 ann {id}。

我无法获取访问令牌,但上面的错误并没有出现。有人可以帮我解决这个问题吗?我已经阅读并实施了几乎所有内容,但它似乎不起作用。

更新: 我能够通过以 {bcrypt} 格式保存密码来解决上述错误。同样在其他需要的地方应用 passwordEncoder。

问题: 我现在遇到凭据错误的错误。我已经调试并发现它没有获得我们试图传入 api 的用户名并接收到 null 参数。流到达 userDetailservice 但带有 epmty 参数。我已经附上了我的 UserDetailsS​​ervice。

SecurityConfig.java

@Configuration
@EnableWebSecurity
public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {

  @Autowired
  private ClientDetailsService clientDetailsService;

  @Autowired
  private UserDetailsService userDetailsService;

  @Autowired
  private CustomPasswordEncoder customPasswordEncoder;

  @Autowired
  public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(customPasswordEncoder);
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
        .anonymous().disable()
        .authorizeRequests()
        .antMatchers("/oauth/token").permitAll();
  }

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

  @Bean
  @Autowired
  public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore) {
    TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
    handler.setTokenStore(tokenStore);
    handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
    handler.setClientDetailsService(clientDetailsService);
    return handler;
  }

  @Bean
  @Autowired
  public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
    TokenApprovalStore store = new TokenApprovalStore();
    store.setTokenStore(tokenStore);
    return store;
  }

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

AuthorizationServerConfig.java

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

    private static String REALM = "api-security";

    @Value("${app.oauth.client-id}")
    private String CLIENT_ID;

    @Value("${app.oauth.client-secret}")
    private String CLIENT_SECRET;

    @Value("${app.oauth.access-token-validity}")
    private int accessTokenValidity;

    @Value("${app.oauth.refresh-token-validity}")
    private int refreshTokenValidity;

    @Autowired
    @Qualifier("tokenStore")
    private TokenStoreService tokenStore;

    @Autowired
    private UserApprovalHandler userApprovalHandler;

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory().withClient(CLIENT_ID)
                .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
                .authorities("ROLE_ADMIN").scopes("read", "write", "trust").secret(passwordEncoder.encode(CLIENT_SECRET))
                .accessTokenValiditySeconds(accessTokenValidity).refreshTokenValiditySeconds(refreshTokenValidity);
        System.out.println(passwordEncoder.encode(CLIENT_SECRET));
        System.out.println(CLIENT_SECRET);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler)
                .authenticationManager(authenticationManager);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.realm(REALM + "/client");
    }
}

UserDetailsService.java

@Configuration
@EnableWebSecurity
public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {

  @Autowired
  private ClientDetailsService clientDetailsService;

  @Autowired
  @Qualifier("userDetailsService")
  private UserDetailsService userDetailsService;


  @Autowired
  public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
        .anonymous().disable()
        .authorizeRequests()
        .antMatchers("/oauth/token").permitAll();
  }

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

  @Bean
  @Autowired
  public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore) {
    TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
    handler.setTokenStore(tokenStore);
    handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
    handler.setClientDetailsService(clientDetailsService);
    return handler;
  }

  @Bean
  @Autowired
  public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
    TokenApprovalStore store = new TokenApprovalStore();
    store.setTokenStore(tokenStore);
    return store;
  }

  @Bean
  public PasswordEncoder passwordEncoder() {
      return PasswordEncoderFactories.createDelegatingPasswordEncoder();
  }

//  @Bean
//  @Override
//  public UserDetailsService userDetailsServiceBean() throws Exception {
//      return super.userDetailsServiceBean();
//  }

//  @Bean
//  public UserDetailsService userDetailsService() {
//    return super.userDetailsService();
//  }
}

对于觉得有用的人,我可以通过以下几点解决这个问题:

  1. 如果您清除访问令牌集合或 table,您将能够获得一次访问令牌,仅此而已。之后您执行的每个请求都会出现“500 错误 - 内部服务器错误”。

  2. 发生这种情况是因为 spring 启动在发出其他请求时无法理解来自数据库的访问令牌,对此您可以使用 "org.springframework.util.SerializationUtils" 包。您可以搜索一下,它会在发出请求时序列化和反序列化访问令牌和刷新令牌。