【问题标题】:Spring boot Oauth2 grant_type password always return invalid_grant Bad CredentialsSpring boot Oauth2 grant_type 密码总是返回 invalid_grant Bad Credentials
【发布时间】:2021-12-03 15:04:03
【问题描述】:

我正在尝试创建一个 API 来负责保护我的其余 API。该api具有为整个集合的用户生成令牌的功能。 用户必须通过 clientId 和 secrt 以及他们的用户名和密码进行身份验证。 为了测试它,我使用了这样的邮递员请求:

  curl --location --request POST 'http://localhost:5101/oauth/token' \
--header 'Authorization: Basic cHJ1ZWJhOnBydWViYQ==' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'username=usuario' \
--data-urlencode 'password=pass' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'scope=all'

授权头由clientId和它的秘钥组成。

grant_typepassword

时,我总是收到 invalid_grant 错误
{
    "error": "invalid_grant",
    "error_description": "Bad credentials"
}

当我使用 grant_type client_credentials 时,它工作正常,它返回客户端令牌。

这是我的

@EnableAuthorizationServer
@SpringBootApplication
public class Auth implements CommandLineRunner {

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    public static void main(String[] args) {
        SpringApplication.run(Auth.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        // TODO Auto-generated method stub
        String password = "pass";
        for (int i = 0; i < 4; i++) {
            String pasBcript = passwordEncoder.encode(password);
            System.out.println(pasBcript);
        }
    }
}

我使用 run 方法为我的数据库用户获取密码。

安全配置

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Autowired
    private UserService userService;
    
    // @Autowired private AuthenticationEventPublisher eventPublisher;
    
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    @Override
    @Autowired
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
        //.and().authenticationEventPublisher(eventPublisher);
    }
    
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

}

AuthorizationServerConfig

@RefreshScope
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter{
    
    @Autowired
    private Environment env;

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;
    
    @Autowired
    private AuthenticationManager authenticationManager;
    

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.tokenKeyAccess("permitAll()") //Endpoint para generar el token public, POST /oauth/token
        .checkTokenAccess("isAuthenticated()"); // validar el toekn
    }

    // Doble autenticacion cliente (aplicacion) y usuarios
    // hay que envioar dos crecenciales las de la aplicacion y las del usuario
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()      
        .withClient("prueba")
        .secret(passwordEncoder.encode("prueba"))
        .scopes("all") // Permiso de la app prueba
        .authorizedGrantTypes("password", "refresh_token", "client_credentials") // Tipo de autenticación, como vamos a obtener el token
        .accessTokenValiditySeconds(3600)
        .refreshTokenValiditySeconds(3600);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter()));
        
        endpoints.authenticationManager(authenticationManager)
        .tokenStore(tokenStore()) // Componente que se encarga de guardar el token
        .accessTokenConverter(accessTokenConverter())
        .tokenEnhancer(tokenEnhancerChain);
    }

    @Bean
    public JwtTokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter tokenConverter = new JwtAccessTokenConverter();
        // Codigo secreto para firmar
        tokenConverter.setSigningKey(Base64.getEncoder().encodeToString(env.getProperty("config.security.oauth.jwt.key").getBytes()));
        return tokenConverter;
    }
    
}

用户服务

@Service
public class UserService implements IUserService, UserDetailsService {

    Logger logger = LoggerFactory.getLogger(UserService.class);
    

    @Autowired
    private IUserRepository userRepository;
    @Override
    public AuthUser loadUserByUsername(String username) {
        return userRepository.findByUsername(username)
                    .orElseThrow(() -> new UsernameNotFoundException("User not found"));
    }

}

POM.XML

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.11</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>net.example.auth</groupId>
    <artifactId>auth-service</artifactId>
    <version>3.0.0</version>
    <packaging>jar</packaging>
    <name>Auth</name>
    <description></description>

    <properties>
        <java.version>11</java.version>
        <spring-cloud.version>2020.0.4</spring-cloud.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <!-- <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>-->

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-client</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
            <version>2.3.8.RELEASE</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-jwt</artifactId>
            <version>1.1.1.RELEASE</version>
        </dependency>
        
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

我确定对于客户端和用户来说,凭据都很好。我已经检查了好几次。 我的想法已经用完了,请问有什么帮助吗?

【问题讨论】:

    标签: java spring-boot spring-security spring-security-oauth2 spring-oauth2


    【解决方案1】:

    问题出在 userRepository 中,我正在通过 username 查找用户,而在我的数据库中,username 是登录字段。我已将用户名更改为登录存储库,现在它可以正常工作了。

    【讨论】:

      猜你喜欢
      • 2015-09-17
      • 2020-03-24
      • 2018-11-02
      • 1970-01-01
      • 2019-02-19
      • 2017-01-30
      • 2012-04-25
      • 1970-01-01
      • 2020-05-24
      相关资源
      最近更新 更多