【问题标题】:Spring Boot JDBC Authentication failing [duplicate]Spring Boot JDBC身份验证失败[重复]
【发布时间】:2020-07-02 16:40:56
【问题描述】:

我正在尝试对使用 Postgresql 数据库的 REST 控制器使用 JDBC 身份验证。 管理身份验证的 Configuration 类如下:

@Configuration
@EnableAutoConfiguration
public class JDBCSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    DataSource dataSource;
    @Autowired
    public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication().dataSource(dataSource)
                .usersByUsernameQuery("select username,password, enabled from users where username=?")
                .authoritiesByUsernameQuery("select username, role from user_roles where username=?");
    }



    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
                //HTTP Basic authentication
                .httpBasic()
                .and()
                .authorizeRequests()
                .antMatchers(HttpMethod.GET, "/**").hasRole("USER")
                .antMatchers(HttpMethod.POST, "/").hasRole("ADMIN")
                .and()
                .csrf().disable()
                .formLogin().disable();
    }


}

数据源配置应该没问题:

spring.datasource.url=jdbc:postgresql://localhost:5432/springdb
spring.datasource.username=user
spring.datasource.password=password

但是,当我尝试调用 Controller 的方法时,使用角色中的用户:

@RequestMapping(path= "/", method = RequestMethod.GET, produces = {"application/json"})
public List<Customer> find()
{
    return repository.getCustomers();
}

然后会导致如下错误:

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
        at org.springframework.security.crypto.password.DelegatingPasswordEncoder$UnmappedIdPasswordEncoder.matches(DelegatingPasswordEncoder.java:244) ~[spring-security-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
        at org.springframework.security.crypto.password.DelegatingPasswordEncoder.matches(DelegatingPasswordEncoder.java:198) ~[spring-security-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
        at org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration$LazyPasswordEncoder.matches(AuthenticationConfiguration.java:289) ~[spring-security-config-5.1.6.RELEASE.jar:5.1.6.RELEASE]

Configuration 类有什么问题吗? 谢谢

【问题讨论】:

  • .formLogin().disable(); 之后在protected void configure(HttpSecurity http) 中添加.passwordEncoder(NoOpPasswordEncoder.getInstance());
  • 你的密码在你的数据库中加密了吗?

标签: spring-boot spring-security


【解决方案1】:

问题

  • 您直接在数据库中创建了用户和密码。但 Spring 安全性要求密码前有前缀。
  • 您正在检查类似hasRole("USER") 的角色,它相当于hasAuthority("ROLE_USER")

解决方案:

  1. 要解决密码问题,您可以使用以下中的任何,但不能同时使用:

    • 如果密码是testing1,您必须将密码存储为{noop}testing1。因此,请相应地更新您在数据库中的密码。

    • NoOpPasswordEncoder bean 定义为您的密码编码器。

  2. 修复authorisation 问题:

    • 在数据库中为您的权限添加前缀ROLE_
@Bean
public PasswordEncoder passwordEncoder() {
    return NoOpPasswordEncoder.getInstance();
}

说明

  • 当你不配置密码编码器时,Spring security 使用DelegatingPasswordEncoder 作为密码编码器。它实际上是以下编码器的列表。
  public static PasswordEncoder createDelegatingPasswordEncoder() {
    String encodingId = "bcrypt";
    Map<String, PasswordEncoder> encoders = new HashMap<>();
    encoders.put(encodingId, new BCryptPasswordEncoder());
    encoders.put("ldap", new LdapShaPasswordEncoder());
    encoders.put("MD4", new Md4PasswordEncoder());
    encoders.put("MD5", new MessageDigestPasswordEncoder("MD5"));
    encoders.put("noop", NoOpPasswordEncoder.getInstance());
    encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
    encoders.put("scrypt", new SCryptPasswordEncoder());
    encoders.put("SHA-1", new MessageDigestPasswordEncoder("SHA-1"));
    encoders.put("SHA-256", new MessageDigestPasswordEncoder("SHA-256"));
    encoders.put("sha256", new StandardPasswordEncoder());
    encoders.put("argon2", new Argon2PasswordEncoder());

    return new DelegatingPasswordEncoder(encodingId, encoders);
}
  • 由于它有一个密码编码器列表,在检索到用户和密码后,它不知道使用哪个密码编码器来加密密码。

  • 为了解决这个问题,spring security 期望在密码中添加一个前缀。因此,如果密码是使用BCryptPasswordEncoder 创建的,它会将其存储为{bcrypt}xxx-sdsa-bcrypt-pasa。所以在检索时,它可以决定使用哪个密码编码器。

【讨论】:

  • 感谢您的详细回答。不幸的是,我已经尝试了这两种解决方案(将 db 密码更改为“{noop}password”并在 @Configuration 类中添加 PasswordEncoder 但是现在我得到了 403 Forbidden (而不是 401 错误)。我猜这通常表示用户/密码正常,但不允许角色访问该资源。
  • 您的角色是否以ROLE_ 前缀存储?如果没有,您也可以将其添加到数据库中吗?你需要上面加上这个改变
  • 不,他们不是 :-( 现在可以了。谢谢你阻止我把头撞到墙上
猜你喜欢
  • 2017-12-06
  • 2021-06-24
  • 2022-08-16
  • 2019-01-06
  • 1970-01-01
  • 1970-01-01
  • 2020-02-06
  • 1970-01-01
  • 2019-05-29
相关资源
最近更新 更多