Spring boot Spring引导JDBC身份验证失败

Spring boot Spring引导JDBC身份验证失败,spring-boot,spring-security,Spring Boot,Spring Security,我正在尝试使用Postgresql数据库对REST控制器使用JDBC身份验证。 管理身份验证的配置类如下所示: @Configuration @EnableAutoConfiguration public class JDBCSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired DataSource dataSource; @Autowired public void configAut

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

@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
但是,当我尝试调用控制器的方法时,用户处于角色:

@RequestMapping(path= "/", method = RequestMethod.GET, produces = {"application/json"})
public List<Customer> find()
{
    return repository.getCustomers();
}
配置类中是否有任何错误? 谢谢

问题

  • 您直接在数据库中创建了用户和密码。但是SpringSecurity希望在密码前面有一个前缀
  • 您正在检查类似于
    hasRole(“用户”)
    的角色,它相当于
    hasAuthority(“角色用户”)
解决方案:

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

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

    • 定义为
      NoOpPasswordEncoder
      bean作为密码编码器

  • 要解决授权问题,请执行以下操作:

    • 在数据库中为您的权限添加前缀
      ROLE\uu
  • 解释

    • 当您未配置密码编码器时,Spring security使用
      DelegatingPasswordEncoder
      作为密码编码器。它实际上是以下编码器的列表
    公共静态密码编码器createDelegatingPasswordEncoder(){
    字符串encodingId=“bcrypt”;
    映射编码器=新的HashMap();
    put(encodingId,新的BCryptPasswordEncoder());
    put(“ldap”,新的LdapShaPasswordEncoder());
    放入(“MD4”,新的Md4PasswordEncoder());
    编码器.put(“MD5”,新的MessageDigestPasswordEncoder(“MD5”);
    put(“noop”,NoOpPasswordEncoder.getInstance());
    put(“pbkdf2”,新的Pbkdf2PasswordEncoder());
    put(“scrypt”,新的SCryptPasswordEncoder());
    编码器。put(“SHA-1”,新的MessageDigestPasswordEncoder(“SHA-1”);
    编码器.put(“SHA-256”,新的MessageDigestPasswordEncoder(“SHA-256”);
    编码器.put(“sha256”,新标准密码编码器());
    put(“argon2”,新的Argon2PasswordEncoder());
    返回新的DelegatingPasswordEncoder(编码ID,编码器);
    }
    
    • 由于它有一个密码编码器列表,在检索用户和密码后,它不知道使用哪个密码编码器来加密密码

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


    添加
    .passwordEncoder(NoOpPasswordEncoder.getInstance())
    after
    .formLogin().disable()
    受保护的void配置(HttpSecurity http)
    中。您的密码在数据库中加密了吗?谢谢您的详细回答。不幸的是,我尝试了这两种解决方案(将db密码更改为“{noop}password”并在@Connfiguration类中添加PasswordEncoder),但是现在我得到了403禁止(而不是401错误)。我猜这通常表示用户/密码正常,但不允许该角色访问该资源。您的角色是否使用
    Role\uu
    前缀存储?如果没有,您也可以将其添加到数据库中吗?您需要上述加上此更改否:-(现在可以了。谢谢您阻止我撞墙。)
    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]
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }
    
      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);
    }