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 @   刚刚好。  阅读(703)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示