Java 为基本身份验证、spring引导安全性获取多个用户

Java 为基本身份验证、spring引导安全性获取多个用户,java,spring-boot,encoding,spring-security,bcrypt,Java,Spring Boot,Encoding,Spring Security,Bcrypt,我有一个用户列表,我想在我的基本身份验证中使用它们 我的代码当前如下所示: @Configuration @EnableWebSecurity public class BasicAuthConfig extends WebSecurityConfigurerAdapter { @Bean public PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();} @Autowired privat

我有一个用户列表,我想在我的基本身份验证中使用它们

我的代码当前如下所示:

@Configuration
@EnableWebSecurity
public class BasicAuthConfig extends WebSecurityConfigurerAdapter {

  @Bean
  public PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}
  @Autowired
  private ConfigService configService;
  // Authentication : User --> Roles
  // NoOpPasswordEncoder has been deprecated in Spring security so {noop} is being used to avoid errors
  protected void configure(AuthenticationManagerBuilder auth)
    throws Exception {
    auth.inMemoryAuthentication().passwordEncoder(passwordEncoder())
      .withUser("someuser")
        .password("somepassword")
        .roles("USER");
  }

  // Authorization : Role -> Access
  protected void configure(HttpSecurity http) throws Exception {
    http
      .httpBasic()
        .and().authorizeRequests()
          .antMatchers("/actuator/**")
            .permitAll()
          .antMatchers("/tokenservice/**")
            .hasRole("USER")
          .antMatchers("/")
            .permitAll()
        .and().csrf()
        .disable()
          .headers()
          .frameOptions()
        .and().disable()
          .sessionManagement()
          .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
  }}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
    DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
    authenticationProvider.setUserDetailsService(userDetailsService());
    authenticationProvider.setPasswordEncoder(passwordEncoder());
    return authenticationProvider;
}
@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService());
    auth.authenticationProvider(authenticationProvider());
}
public class SecUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            User user = userRepository().findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException(username);
        } else {
            Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
            grantedAuthorities.add(new SimpleGrantedAuthority(user.getRole().getName()));

            return new org.springframework.security.core.userdetails.User(user.getName(), user.getPassword(),
                    grantedAuthorities);
        }
    }
}
我想用我的用户列表中的用户名和密码替换“someuser”和“somepassword”。目前,我可以使用
configService.getCOnfigurations().getUsers()
获取列表。 用户只有用户名和密码,这两个字符串。如何将所有用户名和密码输入
.withUser()

**编辑 我在configure中做了一个简单的for循环,应该可以,但是每当我尝试发布到我的API时,它都会说
org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder:99-编码的密码看起来不像bcrypt

我使用在线bcrypt生成器生成密码,它们看起来像这样

<?xml version="1.0" encoding="UTF-8"?>
<Configurations>
    <Port>8007</Port>
    <EnableHttps>true</EnableHttps>
    <KeyStorePath>classpath:ssl-server.jks</KeyStorePath>
    <KeyPass>changeit</KeyPass>
    <TokenTtlMillis>15000</TokenTtlMillis>
  <Users Username="user1">
      <Password>$2y$10$.8VQR6tJub5uVdVLByItQO8QYGZVuWPhLuBUTQSDJAvVpLAUmuqZ2</Password>
  </Users>
  <Users Username="user2">
    <Password>$2y$10$r/CQz7PZp5banmSzr9OiDe2Kxrda4BhXIBXvvouRnm1w3M72wLQj.</Password>
  </Users>
</Configurations>

8007
真的
类路径:ssl-server.jks
换
15000
$2y$10$.8VQR6TJU5UVDVLBYITQ8QYGZVUWPLUBUTQSDJAVVPLAUMUQZ2
$2y$10$r/CQz7PZp5banmSzr9OiDe2Kxrda4BhXIBXvvouRnm1w3M72wLQj。

密码是纯密码和密码2

您可以在
Web安全配置适配器中声明
DAOAuthenticationProvider
,如下所示:

@Configuration
@EnableWebSecurity
public class BasicAuthConfig extends WebSecurityConfigurerAdapter {

  @Bean
  public PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}
  @Autowired
  private ConfigService configService;
  // Authentication : User --> Roles
  // NoOpPasswordEncoder has been deprecated in Spring security so {noop} is being used to avoid errors
  protected void configure(AuthenticationManagerBuilder auth)
    throws Exception {
    auth.inMemoryAuthentication().passwordEncoder(passwordEncoder())
      .withUser("someuser")
        .password("somepassword")
        .roles("USER");
  }

  // Authorization : Role -> Access
  protected void configure(HttpSecurity http) throws Exception {
    http
      .httpBasic()
        .and().authorizeRequests()
          .antMatchers("/actuator/**")
            .permitAll()
          .antMatchers("/tokenservice/**")
            .hasRole("USER")
          .antMatchers("/")
            .permitAll()
        .and().csrf()
        .disable()
          .headers()
          .frameOptions()
        .and().disable()
          .sessionManagement()
          .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
  }}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
    DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
    authenticationProvider.setUserDetailsService(userDetailsService());
    authenticationProvider.setPasswordEncoder(passwordEncoder());
    return authenticationProvider;
}
@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService());
    auth.authenticationProvider(authenticationProvider());
}
public class SecUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            User user = userRepository().findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException(username);
        } else {
            Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
            grantedAuthorities.add(new SimpleGrantedAuthority(user.getRole().getName()));

            return new org.springframework.security.core.userdetails.User(user.getName(), user.getPassword(),
                    grantedAuthorities);
        }
    }
}
并为它提供一个
密码编码器
和一个
用户详细信息服务
的实现, 为此,您必须实现相应的接口及其方法

然后,您可以在
websecurityConfigureAdapter
类中指定您的
authenticationProvider
,如下所示:

@Configuration
@EnableWebSecurity
public class BasicAuthConfig extends WebSecurityConfigurerAdapter {

  @Bean
  public PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}
  @Autowired
  private ConfigService configService;
  // Authentication : User --> Roles
  // NoOpPasswordEncoder has been deprecated in Spring security so {noop} is being used to avoid errors
  protected void configure(AuthenticationManagerBuilder auth)
    throws Exception {
    auth.inMemoryAuthentication().passwordEncoder(passwordEncoder())
      .withUser("someuser")
        .password("somepassword")
        .roles("USER");
  }

  // Authorization : Role -> Access
  protected void configure(HttpSecurity http) throws Exception {
    http
      .httpBasic()
        .and().authorizeRequests()
          .antMatchers("/actuator/**")
            .permitAll()
          .antMatchers("/tokenservice/**")
            .hasRole("USER")
          .antMatchers("/")
            .permitAll()
        .and().csrf()
        .disable()
          .headers()
          .frameOptions()
        .and().disable()
          .sessionManagement()
          .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
  }}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
    DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
    authenticationProvider.setUserDetailsService(userDetailsService());
    authenticationProvider.setPasswordEncoder(passwordEncoder());
    return authenticationProvider;
}
@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService());
    auth.authenticationProvider(authenticationProvider());
}
public class SecUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            User user = userRepository().findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException(username);
        } else {
            Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
            grantedAuthorities.add(new SimpleGrantedAuthority(user.getRole().getName()));

            return new org.springframework.security.core.userdetails.User(user.getName(), user.getPassword(),
                    grantedAuthorities);
        }
    }
}
这样,您的
UserDetailService
将提供所有可用的用户及其凭据,您不必在安全配置中担心这一点

通过这种方式,您可以以您想要的任何方式(简单文件、nosql DB,如MongoDB等)存储凭据,甚至可以更改该实现,而不会影响您使用spring security进行身份验证的方式

您的UserDetailService应该看起来像这样:

@Configuration
@EnableWebSecurity
public class BasicAuthConfig extends WebSecurityConfigurerAdapter {

  @Bean
  public PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}
  @Autowired
  private ConfigService configService;
  // Authentication : User --> Roles
  // NoOpPasswordEncoder has been deprecated in Spring security so {noop} is being used to avoid errors
  protected void configure(AuthenticationManagerBuilder auth)
    throws Exception {
    auth.inMemoryAuthentication().passwordEncoder(passwordEncoder())
      .withUser("someuser")
        .password("somepassword")
        .roles("USER");
  }

  // Authorization : Role -> Access
  protected void configure(HttpSecurity http) throws Exception {
    http
      .httpBasic()
        .and().authorizeRequests()
          .antMatchers("/actuator/**")
            .permitAll()
          .antMatchers("/tokenservice/**")
            .hasRole("USER")
          .antMatchers("/")
            .permitAll()
        .and().csrf()
        .disable()
          .headers()
          .frameOptions()
        .and().disable()
          .sessionManagement()
          .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
  }}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
    DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
    authenticationProvider.setUserDetailsService(userDetailsService());
    authenticationProvider.setPasswordEncoder(passwordEncoder());
    return authenticationProvider;
}
@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService());
    auth.authenticationProvider(authenticationProvider());
}
public class SecUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            User user = userRepository().findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException(username);
        } else {
            Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
            grantedAuthorities.add(new SimpleGrantedAuthority(user.getRole().getName()));

            return new org.springframework.security.core.userdetails.User(user.getName(), user.getPassword(),
                    grantedAuthorities);
        }
    }
}
公共类SecUserDetailsService实现UserDetailsService{
@凌驾
public UserDetails loadUserByUsername(字符串用户名)引发UsernameNotFoundException{
User=userRepository().findByUsername(用户名);
if(user==null){
抛出新用户名NotFoundException(用户名);
}否则{
Set grantedAuthories=new HashSet();
添加(新的SimpleGrantedAuthority(user.getRole().getName());
返回新的org.springframework.security.core.userdetails.User(User.getName(),User.getPassword(),
授权机构);
}
}
}

这里我使用了一个
UserRepository
,负责从您选择的存储中加载所有用户。例如,如果您决定将其存储在文件中,它将从文件中加载所有用户及其密码,并提供方法
findByUsername
,如果找到具有匹配名称的
User
对象,则返回该对象。如果需要,您的存储库还可以删除用户或修改他们的名称。

您可以在
WebSecurity配置适配器中声明
DAOAuthenticationProvider
,如下所示:

@Configuration
@EnableWebSecurity
public class BasicAuthConfig extends WebSecurityConfigurerAdapter {

  @Bean
  public PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}
  @Autowired
  private ConfigService configService;
  // Authentication : User --> Roles
  // NoOpPasswordEncoder has been deprecated in Spring security so {noop} is being used to avoid errors
  protected void configure(AuthenticationManagerBuilder auth)
    throws Exception {
    auth.inMemoryAuthentication().passwordEncoder(passwordEncoder())
      .withUser("someuser")
        .password("somepassword")
        .roles("USER");
  }

  // Authorization : Role -> Access
  protected void configure(HttpSecurity http) throws Exception {
    http
      .httpBasic()
        .and().authorizeRequests()
          .antMatchers("/actuator/**")
            .permitAll()
          .antMatchers("/tokenservice/**")
            .hasRole("USER")
          .antMatchers("/")
            .permitAll()
        .and().csrf()
        .disable()
          .headers()
          .frameOptions()
        .and().disable()
          .sessionManagement()
          .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
  }}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
    DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
    authenticationProvider.setUserDetailsService(userDetailsService());
    authenticationProvider.setPasswordEncoder(passwordEncoder());
    return authenticationProvider;
}
@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService());
    auth.authenticationProvider(authenticationProvider());
}
public class SecUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            User user = userRepository().findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException(username);
        } else {
            Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
            grantedAuthorities.add(new SimpleGrantedAuthority(user.getRole().getName()));

            return new org.springframework.security.core.userdetails.User(user.getName(), user.getPassword(),
                    grantedAuthorities);
        }
    }
}
并为它提供一个
密码编码器
和一个
用户详细信息服务
的实现, 为此,您必须实现相应的接口及其方法

然后,您可以在
websecurityConfigureAdapter
类中指定您的
authenticationProvider
,如下所示:

@Configuration
@EnableWebSecurity
public class BasicAuthConfig extends WebSecurityConfigurerAdapter {

  @Bean
  public PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}
  @Autowired
  private ConfigService configService;
  // Authentication : User --> Roles
  // NoOpPasswordEncoder has been deprecated in Spring security so {noop} is being used to avoid errors
  protected void configure(AuthenticationManagerBuilder auth)
    throws Exception {
    auth.inMemoryAuthentication().passwordEncoder(passwordEncoder())
      .withUser("someuser")
        .password("somepassword")
        .roles("USER");
  }

  // Authorization : Role -> Access
  protected void configure(HttpSecurity http) throws Exception {
    http
      .httpBasic()
        .and().authorizeRequests()
          .antMatchers("/actuator/**")
            .permitAll()
          .antMatchers("/tokenservice/**")
            .hasRole("USER")
          .antMatchers("/")
            .permitAll()
        .and().csrf()
        .disable()
          .headers()
          .frameOptions()
        .and().disable()
          .sessionManagement()
          .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
  }}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
    DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
    authenticationProvider.setUserDetailsService(userDetailsService());
    authenticationProvider.setPasswordEncoder(passwordEncoder());
    return authenticationProvider;
}
@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService());
    auth.authenticationProvider(authenticationProvider());
}
public class SecUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            User user = userRepository().findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException(username);
        } else {
            Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
            grantedAuthorities.add(new SimpleGrantedAuthority(user.getRole().getName()));

            return new org.springframework.security.core.userdetails.User(user.getName(), user.getPassword(),
                    grantedAuthorities);
        }
    }
}
这样,您的
UserDetailService
将提供所有可用的用户及其凭据,您不必在安全配置中担心这一点

通过这种方式,您可以以您想要的任何方式(简单文件、nosql DB,如MongoDB等)存储凭据,甚至可以更改该实现,而不会影响您使用spring security进行身份验证的方式

您的UserDetailService应该看起来像这样:

@Configuration
@EnableWebSecurity
public class BasicAuthConfig extends WebSecurityConfigurerAdapter {

  @Bean
  public PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}
  @Autowired
  private ConfigService configService;
  // Authentication : User --> Roles
  // NoOpPasswordEncoder has been deprecated in Spring security so {noop} is being used to avoid errors
  protected void configure(AuthenticationManagerBuilder auth)
    throws Exception {
    auth.inMemoryAuthentication().passwordEncoder(passwordEncoder())
      .withUser("someuser")
        .password("somepassword")
        .roles("USER");
  }

  // Authorization : Role -> Access
  protected void configure(HttpSecurity http) throws Exception {
    http
      .httpBasic()
        .and().authorizeRequests()
          .antMatchers("/actuator/**")
            .permitAll()
          .antMatchers("/tokenservice/**")
            .hasRole("USER")
          .antMatchers("/")
            .permitAll()
        .and().csrf()
        .disable()
          .headers()
          .frameOptions()
        .and().disable()
          .sessionManagement()
          .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
  }}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
    DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
    authenticationProvider.setUserDetailsService(userDetailsService());
    authenticationProvider.setPasswordEncoder(passwordEncoder());
    return authenticationProvider;
}
@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService());
    auth.authenticationProvider(authenticationProvider());
}
public class SecUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            User user = userRepository().findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException(username);
        } else {
            Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
            grantedAuthorities.add(new SimpleGrantedAuthority(user.getRole().getName()));

            return new org.springframework.security.core.userdetails.User(user.getName(), user.getPassword(),
                    grantedAuthorities);
        }
    }
}
公共类SecUserDetailsService实现UserDetailsService{
@凌驾
public UserDetails loadUserByUsername(字符串用户名)引发UsernameNotFoundException{
User=userRepository().findByUsername(用户名);
if(user==null){
抛出新用户名NotFoundException(用户名);
}否则{
Set grantedAuthories=new HashSet();
添加(新的SimpleGrantedAuthority(user.getRole().getName());
返回新的org.springframework.security.core.userdetails.User(User.getName(),User.getPassword(),
授权机构);
}
}
}

这里我使用了一个
UserRepository
,负责从您选择的存储中加载所有用户。例如,如果您决定将其存储在文件中,它将从文件中加载所有用户及其密码,并提供方法
findByUsername
,如果找到具有匹配名称的
User
对象,则返回该对象。如果需要,您的存储库还可以删除用户或修改他们的姓名。

基于Claudio的回答,使用
DaoAuthenticationProvider

@Bean
public DaoAuthenticationProvider authenticationProvider() {
    DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
    authenticationProvider.setUserDetailsService(userDetailsService());
    authenticationProvider.setPasswordEncoder(passwordEncoder());
    return authenticationProvider;
}

@Override
protected void configure(AuthenticationManagerBuilder auth)
        throws Exception {
    auth.userDetailsService(userDetailsService())
            .authenticationProvider(authenticationProvider());
}

@Override
protected UserDetailsService userDetailsService() {
    return new MyUserDetailsService();
}
UserDetailsService
是代码的真正核心所在。您将提供从XML读取的接口的自定义实现。假设您有一个方法
getPassword(字符串用户名)

至于您的BCrypt问题,
密码
散列给了我一个无效的salt修订错误。尝试直接使用应用程序对其进行哈希,例如:

public static void main(String[] args) {
    System.out.println(new BCryptPasswordEncoder().encode("password"));
}
或者在每行上传递一个带有密码的文件(使用Java 8):

publicstaticvoidmain(字符串[]args)引发IOException{
如果(args.length!=1){
System.out.println(“需要1个指向文件的参数”);
系统出口(1);
}
文件f=新文件(args[0]);
如果(!f.i.)