我有一个spring boot 1.5.9授权服务器,它使用BCrypt存储密码。我正在尝试迁移到2.0,但是,我不再能够检索授权令牌。
服务器的响应是:
"timestamp": "2018-03-09T15:22:06.576+0000",
"status": 401,
"error": "Unauthorized",
"message": "Unauthorized",
"path": "/oauth/token"
}
控制台输出以下内容:2018-03-09 09:22:06.553 WARN 20976---[nio-8090-exec-1]o.s.s.c.bcrypt.bcryptpasswordencoder:编码的密码不像bcrypt
。
这部分应用程序以前工作得很好。我所做的唯一更改是build.gradle文件(更改springbootversion
、添加io.spring.dependency-management
插件和添加运行时('org.springframework.boot:-boot-devtools')
。
buildscript {
ext {
springBootVersion = '2.0.0.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.midamcorp'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-data-rest')
compile('org.springframework.boot:spring-boot-starter-jdbc')
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-starter-security')
compile('commons-io:commons-io:2.5')
compile('org.springframework.security:spring-security-jwt:1.0.7.RELEASE')
compile('org.springframework.security.oauth:spring-security-oauth2:2.2.1.RELEASE')
compile 'com.microsoft.sqlserver:mssql-jdbc:6.2.2.jre8'
runtime('org.springframework.boot:spring-boot-devtools')
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile('org.springframework.security:spring-security-test')
testCompile('com.h2database:h2:1.4.196')
}
中的密码哈希逻辑可在两个单独的配置文件中找到:
package com.midamcorp.auth_server.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.password.PasswordEncoder;
import com.midamcorp.auth_server.service.OAuthUserDetailsService;
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private OAuthUserDetailsService userService;
@Autowired
private PasswordEncoder passwordEncoder;
@Bean
@Override
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
// Hash password
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService)
.passwordEncoder(passwordEncoder);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.httpBasic()
.realmName("test")
.and()
.csrf()
.disable();
}
}
而且
package com.midamcorp.auth_server.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
// Contains properties common to both authorization and resource servers
@Configuration
public class AppConfig {
@Value("${spring.datasource.url}")
private String datasourceUrl;
@Value("${spring.datasource.driverClassName}")
private String dbDriverClassName;
@Value("${spring.datasource.username}")
private String dbUsername;
@Value("${spring.datasource.password}")
private String dbPassword;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(dbDriverClassName);
dataSource.setUrl(datasourceUrl);
dataSource.setUsername(dbUsername);
dataSource.setPassword(dbPassword);
return dataSource;
}
// Refrence: http://www.baeldung.com/spring-security-oauth-jwt
/* !!!!!!!!!!!!!!!!!!!!!!!!!!
** TODO
* Secure key file for deployment.
!!!!!!!!!!!!!!!!!!!! */
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
KeyStoreKeyFactory keyStoreKeyFactory =
new KeyStoreKeyFactory(new ClassPathResource("mytest.jks"), "mypass".toCharArray());
converter.setKeyPair(keyStoreKeyFactory.getKeyPair("mytest"));
return converter;
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
}
OAuthUser类:
package com.midamcorp.auth_server.model;
import java.util.List;
import javax.persistence.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import com.fasterxml.jackson.annotation.JsonIgnore;
@Entity
@Table(name="auth_user")
public class OAuthUser {
// @Autowired
// @Transient
// private PasswordEncoder passwordEncoder;
//
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name= "username")
private String userName;
@Column(name="password")
@JsonIgnore
private String password;
@Column(name="first_name")
private String firstName;
@Column(name="last_name")
private String lastName;
@Column(name="email")
private String email;
@Column(name="is_enabled")
private boolean isEnabled;
/**
* Reference: https://github.com/nydiarra/springboot-jwt/blob/master/src/main/java/com/nouhoun/springboot/jwt/integration/domain/User.java
* Roles are being eagerly loaded here because
* they are a fairly small collection of items for this example.
*/
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "user_role", joinColumns
= @JoinColumn(name = "user_id",
referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "role_id",
referencedColumnName = "id"))
private List<Role> roles;
public OAuthUser() {};
public OAuthUser(String firstName, String lastName, String user, String pass) {
this.firstName = firstName;
this.lastName = lastName;
this.userName = user;
this.password = pass;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public boolean isEnabled() {
return isEnabled;
}
public void setEnabled(boolean isEnabled) {
this.isEnabled = isEnabled;
}
}
我知道spring的安全有很大的变化,但我不确定如何解决这个问题。如有任何指导,将不胜感激。
多谢了。
编辑
只是一些进一步的细节以防万一。即使我在运行spring boot 2.0时添加了一个新用户:
OAuthUser user = new OAuthUser();
user.setFirstName("K");
user.setLastName("M");
user.setPassword(passwordEncoder.encode("L"));
user.setUserName("KLM");
repository.save(user);
它并使用新的用户名和密码发出请求,我仍然收到错误。
编辑二:
请求错误的结果:
curl --request POST \
--url http://web:secret@localhost:8090/oauth/token \
--header 'content-type: multipart/form-data; boundary=---011000010111000001101001' \
--form grant_type=password \
--form username=KLM \
--form password=L
授权服务器配置:
package com.midamcorp.auth_server.config;
import java.util.Arrays;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.AccessTokenConverter;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
// Reference: https://dazito.com/java/spring-boot-and-oauth2-with-jdbc
@EnableAuthorizationServer
@Configuration
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter{
@Autowired
private TokenStore tokenStore;
@Autowired
private AccessTokenConverter converter;
private final AppConfig appConfig;
private AuthenticationManager authenticationManager;
@Autowired
public AuthServerConfig(AuthenticationManager authenticationManager, AppConfig appConfig) {
this.authenticationManager = authenticationManager;
this.appConfig = appConfig;
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.checkTokenAccess("permitAll()");
security.tokenKeyAccess("permitAll()");
}
@Override
public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {
JdbcClientDetailsService details = new JdbcClientDetailsService(appConfig.dataSource());
configurer.jdbc(appConfig.dataSource());
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
endpoints.tokenStore(tokenStore)
.accessTokenConverter(converter)
.authenticationManager(authenticationManager);
}
@Bean
@Primary //Making this primary to avoid any accidental duplication with another token service instance of the same name
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore);
defaultTokenServices.setSupportRefreshToken(true);
return defaultTokenServices;
}
}
我正在使用以下属性:
spring.datasource.url=jdbc:sqlserver://localhost;databaseName=API
spring.datasource.username=**
spring.datasource.password=**
spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
server.port=8090
我用clientSecret密码编码解决了这个问题
@Override
public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {
configurer
.inMemory()
.withClient(clientId)
.secret(encode(clientSecret))
.authorizedGrantTypes(grantType)
.scopes(scopeRead, scopeWrite)
.resourceIds(resourceIds);
}
我无法使用正确的详细信息登录,因为程序不断声明编码的密码看起来不像bcrypt。有人知道怎么解决这个吗?我正在使用JDBC身份验证。 我也有正确的数据库表,有足够的空间用于编码密码。我不确定哪里出了问题。 JSP表单: 安全配置: 登录控制器 我的数据库:这里
我最近遵循了Spring boot安全中的身份验证和授权教程,我想我在谈到sql时迷路了。尽管它没有显示任何错误,即使我输入了正确的用户名和密码,它仍然显示错误的凭据。这是我的代码: UserDetailsServiceImpl.java WebUserMapper.java WebSecurityConfig.java 这是我的数据库: 它返回以下错误: 密码是123。我不知道为什么它不工作,即
我正在使用OAuth2和JPA编写spring boot REST安全API。当访问访问令牌时,我会收到警告,因为编码密码看起来不像BCrypt。当我点击邮递员http://localhost:8080/oauth/token的URL时?grant_type=password&username=user&password=user i get 我已经定义了Bean和存储库。我已经使用了secret
即使输入了正确的电子邮件和密码,同样的错误也会一次又一次地出现。 更多参考请参见我的回复-https://github.com/ajitlol404/smartcontactmanager/tree/master/smartcontactmanager 控制台错误
问题内容: 我正在尝试使用JWT实施spring AuthorizationServer。我能够生成JWT令牌并登录,直到将BCrypt添加到混合中为止。现在,当我尝试登录时,我从API获得“错误的凭据”。 OAuth2Configuration.java WebSecurityConfig.java SeedData.java 谢谢你的帮助。 问题答案: 我需要进行以下更改才能使其正常工作。如果
我正在使用spring boot,spring安全,OAuth2和JWT来验证我的应用程序,但我一直得到这个令人讨厌的错误,我不知道什么是错误的。我的类: : : 除: 我的实体模型类是: 实体: 实体: 我在数据库中的密码是正确加密的spring安全BCrypt,它的数据类型是varchar(255),大于60。