我目前正在开发自己的项目,该项目应该具有使用spring-boot和spring-oauth的自己的oauth认证服务器。
我知道
TokenEndpoint:处理错误:InvalidGrantException,错误的凭据,甚至名称和密码也正确。
我将用户保存在mysql中,并使用bCrypt
对密码进行编码。
以下是我的配置
我尝试过:
@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] o.s.s.o.provider.endpoint.TokenEndpoint:处理错误:InvalidGrantException,错误的凭据
URL:http://localhost:8088/oauth/token 该请求使用以下参数进行url-www-form-encoded
和“基本身份验证”,用户名为“ my-trusted-client”,密码为“ secret”。
答案 0 :(得分:0)
由于未提供请求,因此我不得不猜测:在配置了ClientDetailsServiceConfigurer
时,您不应该对客户端密码进行编码。
将.secret(passwordEncoder.encode("secret"))
替换为.secret("secret")
,该异常将消失。
答案 1 :(得分:0)
对我的受信任客户端使用.secret("{bcrypt}" + passwordEncoder.encode("secret"))
,对管理员使用.secret("{bcrypt}" + passwordEncoder.encode("adminPassword"))
。并且:检查调试会话中是否使用了BcryptPasswordEncoder。