从Spring引导版本1.5.7迁移到2.0时发生Oauth 2.0错误,在1.5.7.RELEASE上运行良好



我在Spring Boot 1.5.7中实现了Oauth,但当我切换到2时,它显示了错误"java.lang.IllegalArgumentException:没有为id"null"映射的PasswordEncoder。

从一些研究中,我发现这可能是关于密码存储和密码编码的问题。

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

我还尝试过用{bcrypt}作为前缀保存密码,因为springsecurity5在密码搜索过程中会查找ann{id}。

我无法获取访问令牌,上述错误也不会发生。有人能帮我弄清楚吗?我已经阅读并实现了几乎所有的东西,但它似乎不起作用。

更新:我能够通过用{bcrypt}格式保存密码来解决上述错误。类似地,在其他必需位置应用passwordEncoder。

问题:我现在面临一个凭据错误。我已经调试并认为它没有得到我们试图在api中传递的用户名,并且接收到null参数。流到达userDetailservice,但带有一个epmty参数。我已经附上了我的UserDetailsService。

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. 如果您清除访问令牌集合或表,您将能够获得一次访问令牌,但仅此而已。此后您所做的每个请求都将显示"500错误-内部服务器错误"。

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

相关内容

最新更新