用户管理

UserDetails : 用户在 spring security 中的描述 。比如一个用户的姓名,密码等等
UserDetailsService: 用户在 spring security 中行为的描述,比如如何通过用户名找到用户,用户是否已经认证等等
GrantedAuthority: 允许用户是否可以执行一些定义好的行为
UserDetailsManager: 拓展自 UserDetailsService,多了一些额外的行为,比如增删改查用户信息等等。

架构

在具体的用户管理中,其代码关系如下所示:
image.png
从架构图可以得知 UserDetailsService 使用 UserDetails. 所以第一步就需要我们根据 spring-security 里面对 UserDetails 的定义进行自己的实现。

用户管理

UserDetails

先看一下 spring security 是如何描述 UserDetails 的:
image.png
UserDetails 跟 User 类比较相近,但是为了以后更好的维护,需要将这两个类分开创建。

  1. 创建 CustomUserDetails 类 ```java @Component public class CustomerUserDetails implements UserDetails { @Autowired User user;

    public CustomerUserDetails(User user){

    1. this.user = user;

    }

    public final User getUser() {

     return user;
    

    }

    @Override public Collection<? extends GrantedAuthority> getAuthorities() {

     return null;
    

    }

    @Override public String getPassword() {

     return this.user.getPassword();
    

    }

    @Override public String getUsername() {

     return this.user.getUsername();
    

    }

    @Override public boolean isAccountNonExpired() {

     return false;
    

    }

    @Override public boolean isAccountNonLocked() {

     return false;
    

    }

    @Override public boolean isCredentialsNonExpired() {

     return false;
    

    }

    @Override public boolean isEnabled() {

     return true;
    

    } }


<a name="5uc8M"></a>
## UserDetailsService
创建完 UserDetails 以后,我们需要定义其行为。

2. 创建 CustomUserDetailsService 类
```java
@Component
public class CustomUserDetailsService implements UserDetailsService {
    @Autowired
    UserMapper userMapper;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userMapper.selectByName(username);
        if (user == null) {
            throw new UsernameNotFoundException("No found");
        }

        return new CustomerUserDetails(user);
    }
}

UserDetailsService 类只有一个关键的方法,就是 loadUSerByName; 用来寻找用户是否存在。当然,这样远远不够,因为我们也没有认证,因此,我们需要实现 CustomAuthenticationProvider 类来进行密码的验证

AuthenticationProvider

  1. 创建认证类 ```java @Component public class CustomAuthenticationProvider implements AuthenticationProvider { @Autowired CustomUserDetailsService userDetailsService; @Autowired PasswordEncoder passwordEncoder; @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException {

     String username = authentication.getName();
     String password = String.valueOf(authentication.getCredentials());
     UserDetails userDetails = userDetailsService.loadUserByUsername(username);
     if (passwordEncoder.matches(password,userDetails.getPassword())){
         return new UsernamePasswordAuthenticationToken(
                 userDetails.getUsername(),
                 userDetails.getPassword(),
                 null
         );
     }else{
         throw new BadCredentialsException("Bad Credentials");
     }
    

    }

    @Override public boolean supports(Class<?> aClass) {

     return UsernamePasswordAuthenticationToken.class.isAssignableFrom(aClass);
    

    }


4. 最后集成到配置文件里面
```java
@Configuration
@EnableWebSecurity
@ComponentScan(basePackages = {"com.example"})
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    CustomAuthenticationProvider customAuthenticationProvider;

    @Bean
    public PasswordEncoder getDelegatingPasswordEncoder(){
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

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