当前位置:   article > 正文

【Spring Security】2. 自定义UserDetailsService

自定义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;
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

自定义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();
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

方式二: 往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();
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

方式三: 使用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();
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

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

  • 方式一和方式二的作用都是为全局AuthenticationManager配置一个UserDetailsService实例,如果同时使用这两种方式,则以第一种方式为准。Spring Security默认策略是如果configure(AuthenticationManagerBuilder)方法被重写,则使用传入AuthenticationManagerBuilder
    构建AuthenticationManager;否则,按类型自动构建AuthenticationManager
  • 方式三配置的是一个局部AuthenticationManager配置。如果同时使用第一种和第三种配置方式,当进行用户身份验证时,首先会通过局部的
    AuthenticationManager对象进行验证,如果验证失败,则会调用其parent也就是全局的AuthenticationManager再次进行验证。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/370531
推荐阅读
相关标签
  

闽ICP备14008679号