Spring 启动 Oauth2 grant_type 密码总是 return invalid_grant 错误的凭据
Spring boot Oauth2 grant_type password always return invalid_grant Bad Credentials
我正在尝试创建一个 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'
授权header由clientId及其密钥组成。
当grant_type是密码[=52时,我总是得到invalid_grant错误 =]
{
"error": "invalid_grant",
"error_description": "Bad credentials"
}
当我使用 grant_type client_credentials 时它工作正常,它 returns 客户端令牌。
这是我的 Main class
@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);
}
}
}
我已经使用 运行 方法获取我的数据库用户的密码。
安全配置
@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>
我确信凭据对客户端和用户都没有问题。我已经检查过好几次了。
我已经 运行 没主意了,请帮忙??
问题出在 userRepository,我通过 username 查找用户,在我的数据库中 username 是登录字段。我已更改用户名以登录存储库,现在它可以正常工作了。
我正在尝试创建一个 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'
授权header由clientId及其密钥组成。
当grant_type是密码[=52时,我总是得到invalid_grant错误 =]
{
"error": "invalid_grant",
"error_description": "Bad credentials"
}
当我使用 grant_type client_credentials 时它工作正常,它 returns 客户端令牌。
这是我的 Main class
@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);
}
}
}
我已经使用 运行 方法获取我的数据库用户的密码。
安全配置
@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>
我确信凭据对客户端和用户都没有问题。我已经检查过好几次了。 我已经 运行 没主意了,请帮忙??
问题出在 userRepository,我通过 username 查找用户,在我的数据库中 username 是登录字段。我已更改用户名以登录存储库,现在它可以正常工作了。