TokenEndpoint:处理错误:InvalidGrantException,带有正确凭据的错误凭据

时间:2019-07-24 13:52:40

标签: spring spring-security oauth-2.0

我目前正在开发自己的项目,该项目应该具有使用spring-boot和spring-oauth的自己的oauth认证服务器。

我知道

  

TokenEndpoint:处理错误:InvalidGrantException,错误的凭据,甚至名称和密码也正确。

我将用户保存在mysql中,并使用bCrypt对密码进行编码。 以下是我的配置

我尝试过:

  • {noop}密码
  • 尝试了passwordEncoder Bean的不同实现
  • 试图使用自定义UserDetailsS​​erviceImplementation
    @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

  • grant_type:密码
  • 用户名:admin
  • password:adminPassword

和“基本身份验证”,用户名为“ my-trusted-client”,密码为“ secret”。

2 个答案:

答案 0 :(得分:0)

由于未提供请求,因此我不得不猜测:在配置了ClientDetailsServiceConfigurer时,您不应该对客户端密码进行编码。

.secret(passwordEncoder.encode("secret"))替换为.secret("secret"),该异常将消失。

答案 1 :(得分:0)

对我的受信任客户端使用.secret("{bcrypt}" + passwordEncoder.encode("secret")),对管理员使用.secret("{bcrypt}" + passwordEncoder.encode("adminPassword"))。并且:检查调试会话中是否使用了BcryptPasswordEncoder。