【发布时间】:2019-12-02 16:56:42
【问题描述】:
我目前正在开发自己的项目,该项目应该有自己的使用 spring-boot 和 spring-oauth 的 oauth 身份验证服务器。
我明白了
TokenEndpoint : 处理错误:InvalidGrantException,错误的凭据,即使名称和密码都是正确的。
我将我的用户保存在 mysql 中,并使用bCrypt 对密码进行编码。
以下是我的配置
我试过了:
- 密码中的{noop}
- 尝试了 passwordEncoder Bean 的不同实现
- 尝试使用自定义 UserDetailsServiceImplementation
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private PasswordEncoder passwordEncoder;
/**
* Setting up the endpointsconfigurer authentication manager.
* The AuthorizationServerEndpointsConfigurer defines the authorization and token endpoints and the token services.
* @param endpoints
* @throws Exception
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
endpoints.tokenStore(getTokenStore());
}
@Bean
public TokenStore getTokenStore(){
return new InMemoryTokenStore();
}
/**
* Setting up the clients with a clientId, a clientSecret, a scope, the grant types and the authorities.
* @param clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("my-trusted-client")
.authorizedGrantTypes("password")
.authorities("ROLE_USER").scopes("read","write","trust")
.resourceIds("oauth2-resource").accessTokenValiditySeconds(5000).secret(passwordEncoder.encode("secret"));
}
/**
* We here defines the security constraints on the token endpoint.
* We set it up to isAuthenticated, which returns true if the user is not anonymous
* @param security the AuthorizationServerSecurityConfigurer.
* @throws Exception
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.checkTokenAccess("isAuthenticated()");
}
}
public class CustomUserDetails implements UserDetails {
private String password;
private String username;
private Collection<? extends GrantedAuthority> authorities;
public CustomUserDetails(User user) {
this.username = user.getUsername();
this.password = user.getPassword();
this.authorities = translate(user.getRole());
}
private Collection<? extends GrantedAuthority> translate(Role role) {
List<GrantedAuthority> authorities = new ArrayList<>();
String roleName = role.getRole().toUpperCase();
authorities.add(new SimpleGrantedAuthority(roleName));
return authorities;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/","/home","/register","/login").permitAll()
.antMatchers("/private/**").authenticated()
.antMatchers("/post").authenticated()
.antMatchers("/post/postComment").authenticated()
.antMatchers(HttpMethod.DELETE , "/post/**").hasAuthority("ROLE_ADMIN");
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
@SpringBootApplication
@EnableAuthorizationServer
public class BackendApplication {
@Autowired
private PasswordEncoder passwordEncoder;
public static void main(String[] args) {
SpringApplication.run(BackendApplication.class, args);
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
/**
* Password grants are switched on by injecting an AuthenticationManager.
* Here, we setup the builder so that the userDetailsService is the one we coded.
* @param builder
* @param repository
* @throws Exception
*/
@Autowired
public void authenticationManager(AuthenticationManagerBuilder builder, UserRepository repository, UserService userService) throws Exception {
if (repository.count()==0) {
userService.save(new User("admin", "{noop}adminPassword", new Role("ROLE_USER")));
}
builder.userDetailsService(userDetailsService(repository)).passwordEncoder(passwordEncoder);
}
/**
* We return an istance of our CustomUserDetails.
* @param repository
* @return
*/
private UserDetailsService userDetailsService(final UserRepository repository) {
return username -> new CustomUserDetails(repository.findByUsername(username));
}
}
警告信息: 2019-07-24 15:46:42.341 WARN 73936 --- [nio-8088-exec-4] os.s.o.provider.endpoint.TokenEndpoint:处理错误:InvalidGrantException,错误凭据
网址:http://localhost:8088/oauth/token 请求是带有参数的 url-www-form-encoded:
- grant_type:password
- 用户名:管理员
- 密码:admin密码
和“基本身份验证”,用户名“my-trusted-client”,密码“secret”。
【问题讨论】:
-
用户密码错误。我认为您必须在
userService.save(new User("admin", "{noop}adminPassword", new Role("ROLE_USER")));使用 BCrypt 编码器而不是 noop 编码器 -
同样的问题。我可以删除 {noop} 并添加 {bcrypt} 或者只使用普通的“adminPassword”。凭据仍然很差
-
不,您必须使用编码密码:` {bcrypt}$2y$12$G1/7T9nRB9SNBF93Kpe..uhzy2W1mHqoaJZ2zxK.1TJ6mRHWM902a`。
-
或使用密码编码器:
userService.save(new User("admin", passwordEncoder.encode("adminPassword"), new Role("ROLE_USER")));在启动应用程序之前不要忘记从数据库中删除用户。 -
你能解决这个问题吗?我也一样。
标签: spring spring-security oauth-2.0