Java 迁移到Spring Boot 2-安全编码密码看起来不像BCrypt

Java 迁移到Spring Boot 2-安全编码密码看起来不像BCrypt,java,spring,spring-boot,spring-security,Java,Spring,Spring Boot,Spring Security,我有一个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" } 控制台输出以下内容:2

我有一个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警告20976---[nio-8090-exec-1]o.s.s.c.bcrypt.BCryptPasswordEncoder:编码的密码看起来不像bcrypt

这个应用程序以前工作得很好。我所做的唯一更改是build.gradle文件(更改
springBootVersion
,添加
io.spring.dependency management
插件,并添加
运行时('org.springframework.boot:spring boot devtools')

在中散列密码的逻辑可在两个单独的配置文件中找到:

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();

    }
}

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;
    }
}
当我使用新的用户名和密码发送请求时,我仍然收到错误

编辑两个:

请求错误的结果:

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);
}

当oauth2 Dependencies迁移到云计算时,我开始面临这个问题

<dependency>
        <groupId>org.springframework.security.oauth</groupId>
        <artifactId>spring-security-oauth2</artifactId></dependency>
<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-oauth2</artifactId>
    </dependency>

希望这会对你有所帮助。

只是因为这些记录可能会对其他人有所帮助。我也有类似的问题,我注意到了

passwordEncoder.encode(rawPassword, hashedPassword)

输入参数的顺序很重要。第一个参数应该是rawPassword,第二个参数应该是hashedPassword。我出现这个问题是因为我交换了输入参数序列。

@dur Sure,“L”的值(上面插入的新用户的密码)是$2a$10$YI5SRl5OwiLS//AL.zGo/O6YxLWogcbIPkV54Zp9F7TXZ4Tk6JXRe@dur这是一个用户密码。我添加了相同的curl请求(使用失眠客户端生成)上面。Thank.Spring-boot 2实际上涉及重命名许多属性。您是否查看发行说明以确认您没有使用已重命名但尚未更新的属性?您是否使用Spring security 5?如果是这样,您可能必须迁移密码,并使用适当的编码器符号作为前缀,如图所示ed你解决问题了吗?我在使用Spring Boot 2的新应用程序时遇到了同样的问题。我正在使用新的密码格式,测试解码是否有效,但在尝试获取令牌时遇到了相同的错误。
<dependency>
        <groupId>org.springframework.security.oauth</groupId>
        <artifactId>spring-security-oauth2</artifactId></dependency>
<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-oauth2</artifactId>
    </dependency>
@Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
         clients
                .inMemory()
                .withClient("clientapp")
                .authorizedGrantTypes("password","refresh_token")
                .authorities("USER")
                .scopes("read", "write")
                .resourceIds(RESOURCE_ID)
                .secret(passwordEncoder.encode("SECRET"));
    }
passwordEncoder.encode(rawPassword, hashedPassword)