SpringSecurity(二):认证

快速入门

1.引入依赖

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2.编写controller

@RestController
public class HelloController{
@GetMapping("/hello")
public String hello(){
return "hello world";
}
}

启动项目后。我们发现访问'/hello'接口,会自动跳转到'/login'界面

下面我们来看一下这个流程

用户的生成

我们先来看一下spring security默认的用户生成
Spring Security使用UserDetailsService接口向认证器传入一个User实例(org.springframework.security.core.userdetails.User,有三个参数name,password,roles),如果我们还需要用户的其它信息比如验证码之类的,我们需要自己实现一个UserDetails实现类,否则使用默认的(org.springframework.security.core.userdetails.User)即可


public class User implements UserDetails {
    private String username;
    private String password;
    private Boolean rememberMe;
    private String verifyCode;
    private String power;
    private Long expirationTime;
    private List<String> roles;

    /**
    * 省略其它的 get set 方法
    */


    //注意这个方法的返回类型是List<SimpleGrantedAuthority>,所以需要进行转换!
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<SimpleGrantedAuthority> authorities=new ArrayList<>();
        for(String s:roles){
         authorities.add(new SimpleGrantedAuthority(s));

      }
      return authorities;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

接下来我们看下UserDetailsService的源码

public interface UserDetailsService{
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}

loadUserByUsername有一个参数username接收用户认证时传入的用户名,开发中一般我们需要自定义实现UserDetailsService

Spring Security也为UserDetailsService提供了默认实现,InMemoryUserDetailsManager就是一种基于内存的实现。

默认情况下,Spring Security会提供一个InMemoryUserDetailsManager实例,可以通过SecurityPropertes类的getUser()方法获取到一个User实例(org.springframework.security.core.userdetails.User)

@configurationProperties(profix="spring.security")  //加载配置文件,因此可以在配置文件中指定账号密码
public class SecurityProperties{
   private User user=new User();
   public User getUser(){
   return this.user;
   }
   public static class User{
   private String name="user";
   private String password=UUID.randomUUID().toString();
   private List<String> roles=new ArrayList<>();
}
}

可以看到默认账号为user,密码为一串随机的UUID。同时,默认的密码会由getOrDeducePassword方法进行加密,如果没有指定加密方法,则只是会加一个前缀{noop}表明是明文存储。

自定义从数据库获取用户

1.可以自定义一个UserDetails的实现类,也可以使用security的User类,区别在上边已经讲过了

2.自定义UserDetailsService实现类

//注意注册为bean交给容器管理
@Component
public class UserDateService implements UserDetailsService {
    @Autowired
    UserMapper userMapper;
    @Override
    public UserDetails loadUserByUsername(String phone) throws UsernameNotFoundException {
        //这是通过username查询获取一组数据将获得的数据传给security的User
        com.wang.pojo.User user = userMapper.getUserByPhone(phone);
        //如果用户没找到,则抛出UsernameNotFoundException异常
        if (user == null) {
            throw new UsernameNotFoundException("该用户不存在!");
        }
        //把获得的账号密码传给security的User
        return new User(user.getPhone(), user.getPassword(), new ArrayList<>());
    }
}

3.把UserDateService注入到配置类中

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{
//注入我们自定义的UserDateService 实例
@Autowired
UserDateService userDateService;

//注意是参数为AuthenticationManagerBuilder的configure方法
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
auth.userDetailsService(userDateService);

}
....


}
posted @ 2021-05-19 15:42  刚刚好。  阅读(739)  评论(0)    收藏  举报