【Spring Security】2. 自定义UserDetailsService

快速入门中通过在application.yml配置用户名和密码的方式初步了解如何应用Spring Security;但在实际应用中,通常需要从数据库中获取用户信息。

Spring Security中UserDetails相关类

  • UserDetails来表示用户的核心信息:权限集,密码,用户名,账户是否过期,账户是否锁定,凭证是否过期,用户是否可用。在实际开发中,需要扩展UserDetails来自定义存储更多的用户信息。
  • UserDetailsService是Spring Security加载用户数据的核心接口,提供了根据用户名查找用户的方法。
  • UserDetailsManager继承自UserDetailsService,并提供了管理用户的方法。

扩展UserDetailsService

UserDetailsService接口中只声明了一个loadUserByUsername(String username)方法,用于根据用户名查找用户的方法,返回UserDetails


public class CustomizeUserDetailsService implements UserDetailsService {
    // 用于模拟从数据库查询
    private final List<String> usernameList;
    public CustomizeUserDetailsService(List<String> usernameList) {
        this.usernameList = usernameList;
    }
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if(!exists(username)) {
            throw new UsernameNotFoundException("用户不存在");
        }
        // 此处的TEST表示用户的权限, {xxx}指定密码加密的方式, {noop}表示不加密,采用明文
        return User.withUsername(username).authorities("TEST").password("{noop}123456").build();
    }

    private boolean exists(String username) {
        boolean exist = false;
        for(String item : usernameList) {
            if(item.equals(username)) {
                exist = true;
                break;
            }
        }
        return exist;
    }
}

自定义UserDetailsService后还需要将其配置到Spring Security中,才能在用户认证时被使用,大致有以下三种方式将自定义UserDetailsService配置Spring Security中。

方式一: 重写configure(AuthenticationManagerBuilder auth)


@Configuration
public class WebSecurityConfig1 extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        List<String> usernameList = Collections.singletonList("user");
        auth.userDetailsService(new CustomizeUserDetailsService(usernameList));
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .csrf().disable();
    }
}

方式二: 往Spring容器中注入UserDetailsService实例


@Configuration
public class WebSecurityConfig2 extends WebSecurityConfigurerAdapter {
    
    @Override
    @Bean
    protected UserDetailsService userDetailsService() {
        List<String> usernameList = Collections.singletonList("user");
        return new CustomizeUserDetailsService(usernameList);
    }
    
    /* 
    此处作用与userDetailsService()一样,但二者不能同时存在,否则会导致AuthenticationManager构建失败
    @Bean
    public UserDetailsService customizeUserDetailsService() {
        List<String> usernameList = Collections.singletonList("user");
        return new CustomizeUserDetailsService(usernameList);
    }*/

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .csrf().disable();
    }
}

方式三: 使用HttpSecurity设置局部UserDetailsService


@Configuration
public class WebSecurityConfig3 extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        List<String> usernameList = Collections.singletonList("user");
        http.authorizeRequests().anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .userDetailsService(new CustomizeUserDetailsService(usernameList))
                .csrf().disable();
    }
}

先简单对比以上三种方式:

  • 方式一和方式二的作用都是为全局AuthenticationManager配置一个UserDetailsService实例,如果同时使用这两种方式,则以第一种方式为准。Spring Security默认策略是如果configure(AuthenticationManagerBuilder)方法被重写,则使用传入AuthenticationManagerBuilder
    构建AuthenticationManager;否则,按类型自动构建AuthenticationManager
  • 方式三配置的是一个局部AuthenticationManager配置。如果同时使用第一种和第三种配置方式,当进行用户身份验证时,首先会通过局部的
    AuthenticationManager对象进行验证,如果验证失败,则会调用其parent也就是全局的AuthenticationManager再次进行验证。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值