SpringSecurity学习笔记之三:配置用户存储




  没有用户存储的应用相当于没有用户,因为任何用户都会被拒之门外。我们所需要的是用户存储,也就是用户名、密码以及其他信息存储的地方,在进行认证决策的时候,会对其进行检索。Spring Security非常灵活,能够基于各种数据存储来认证用户。它内置了多种常见的用户存储场景,如内存、关系型数据库以及LDAP。同时,我们也可以编写并插入自定义的用户存储实现。借助Spring Security的Java配置,我们能够很容易地配置一个或多个数据存储方案。

使用基于内存的用户存储

重写chonfigure(AuthenticationManagerBuilder)方法可以方便地配置Spring Security对认证的支持。通过inmMemoryAuthentication()方法,我们可以启用、配置并任意填充基于内存的用户存储。实例如下:

package spittr.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.security.web.authentication.rememberme.InMemoryTokenRepositoryImpl;
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception{
        auth.inMemoryAuthentication().withUser("user").password("password").roles("USER").and().withUser("admin").password("password").roles("USER","ADMIN");
    }
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

withUser()方法返回的是UserDetailsManagerConfigurer.UserDetailsBuilder,这个对象提供了多个进一步配置用户的方法,如上面的为用户设置密码的password()方法、授予用户多个角色权限的roles()方法。UserDetailsManagerConfigurer.UserDetailsBuilder对象的更多方法如下表:

这里写图片描述

roles()方法是authorities()方法的简写形式。roles()方法所给定的值都会添加一个“ROLE_”前缀,并将其作为权限授予给用户。如下的配置和上面的等价:

auth.inMemoryAuthentication()
.withUser("user").password("password").authorities("ROLE_USER").and()
.withUser("admin").password("password").authorities("ROLE_USER","ROLE_ADMIN");
  
  
  • 1
  • 2
  • 3

基于数据库表进行认证

用户数据通常会存储在关系型数据库中,并通过JDBC进行访问。所需的最少配置如下:

@Autowired
DataSource dataSource;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
    auth
       .jdbcAuthentication()
         .dataSource(dataSource);
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

我们使用JDBCAuthentication()方法来实现一JDBC为支撑的用户存储,必须要配置的只是一个DataSource,就能访问关系型数据库了。

重写默认的用户查询功能

Spring Security内部默认的查询语句是写定的,可能在某些情况下并不适用。我们可以按照如下的方式配置自己的查询:

@Override
protected void configure(Authentication auth) throws Exception{
    auth
      .jdbcAuthentication()
         .dataSource(dataSource)
            .usersByUsernameQuery("select username,password,true from Spitter where username=?")
            .authoritiesByUsernameQuery("select username,'ROLE_USER' from Spitter where username=?");
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在本例中,我们只重写了认证和基本权限的查询语句,但是通过调用groupAuthoritiesByUsername()方法,我们也能够将群组权限重写为自定义的查询语句。将默认的SQL查询替换为自定义的设计时,很重要的一点就是要遵循查询的基本协议。所有查询都将用户名作为唯一的参数。

使用转码后的密码

通常数据库中的密码都会加密,那么如果我们只是按照上面那样配置的话,用户提交的明文密码和数据库的加密密码就会不匹配,从而认证失败。为了解决这个问题,我们需要借助passwordEncoder()方法指定一个密码转码器:

@Override
protected void configure(Authentication auth) throws Exception{
    auth
      .jdbcAuthentication()
         .dataSource(dataSource)
            .usersByUsernameQuery("select username,password,true from Spitter where username=?")
            .authoritiesByUsernameQuery("select username,'ROLE_USER' from Spitter where username=?")
            .passwordEncoder(new StandardPasswordEncoder("53cr3t"));
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

passwordEncoder()方法可以接受Spring Security中PasswordEncoder接口的任意实现。Spring Security的加密模块包括三个这样的实现:BCryptPasswordEncoder、NoOpPasswordEncoder和StandardPasswordEncoder。

配置自定义的用户服务

如果我们需要认证的用户存储在非关系型数据库中,如Mongo或Neo4j,那么我们需要提供一个自定义的UserDetailsService接口实现。UserDetailsService接口非常简单:

public interface UserDetailsService{
    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
  
  
  • 1
  • 2
  • 3

我们需要做的就是实现loadUserByUsername()方法,根据给定的用户名来查找用户。该方法会返回代表给定用户的UserDetails对象。当我们自定义的配置类完成后,以SpitterUserService(实现了UserDetailsSevice接口并重写了loadUserByUsername方法)为例,可以通过如下方式将其配置为用户存储:

@Autowired
SpitterRepository spitterRepository;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
   auth.userDetailsService(new SpitterUserSevice(spitterRepository));
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6


  没有用户存储的应用相当于没有用户,因为任何用户都会被拒之门外。我们所需要的是用户存储,也就是用户名、密码以及其他信息存储的地方,在进行认证决策的时候,会对其进行检索。Spring Security非常灵活,能够基于各种数据存储来认证用户。它内置了多种常见的用户存储场景,如内存、关系型数据库以及LDAP。同时,我们也可以编写并插入自定义的用户存储实现。借助Spring Security的Java配置,我们能够很容易地配置一个或多个数据存储方案。

猜你喜欢

转载自blog.csdn.net/qq_34531925/article/details/80756810
今日推荐