Spring Security 的作为守门员,其两大功能:认证(Authentication) 和 授权(authorization)

学而思:

  • Spring Security 是如何对用户进行管理的?

初始化项目并启动

初始化一个 Spring Boot 项目并编写一个接口,在没有引入 Spring Security 依赖时,接口是能够能正常访问的。

@RestController
@RequestMapping("/user")
public class UmsAdminController {
    @GetMapping("/details")
    public Object userInfos() {
        return "用户详情";
    }
}
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
    <scope>test</scope>
</dependency>

在引入依赖后,再次请求接口 http://localhost:8080/user/details ,页面跳转至了登录页面。

image-20221014152633274

用户默认名为 user , 默认密码是每次启动应用时随机生成的,启动应用时,显示在了控制台中。

image-20221014152736895

UserDetailsManager

明明什么都没干,只是引入安全的框架,为什么请求接口就被拦截?

这就与 Spring Security 的机制有关,Spring Security 采用了”默认拒绝“ 的安全策略。意思是资源默认对未认证授权用户禁止访问。为需要开放的资源进行属性配置,而不是默认对资源进行开放,这被认为是一种良好的安全做法。

在请求接口前,Spring Security 采用了过滤器对接口进行拦截认证(过滤器是Security 的核心部分,这个之后再详述)。认证过程中用到 UserDetailsManager ,也就是本章的主角。

UserDetailsManager 是管理用户的接口,继承了 UserDetailsService 接口,UserDetailsService 提供了加载用户详细信息(UserDetails)的方法(loadUserByUsername) 。

  • UserDetails: 用户详细信息的接口,对用户的抽象,提供了获取用户名和密码等方法
  • UserDetailsService:提供了一个加载用户的方法,该方法根据用户名从存储(内存、数据库等)中查询出用户对象(UserDetails),认证过程最终就是通过调用该方法,来认证用户。
  • UserDetailsManager:在 UserDetailsService 基础上增加了 增删改等功能,实现了对用户的管理。

image-20221014160843027

两个实现类

在Spring Security 中 ,UserDetailsManager 有两个实现类,如下图:

  • InMemoryUserDetailsManager:基于内存的用户管理器,项目初始化时默认使用,不能满足业务需求
  • JdbcUserDetailsManager:基于数据库的用户管理器,更符合真实业务的需求

image-20221014160754968

InMemoryUserDetailsManager

先来探索 InMemoryUserDetailsManager 在Security 中是如何构建的。

在 Spring Boot 中有一个自动配置类 UserDetailsServiceAutoConfiguration 。向Ioc 容器中注入了 InMemoryUserDetailsManager 对象。

image-20221014164154494

在 构建 InMemoryUserDetailsManager 对象的同时,向其注入了一个 User对象(UserDetails 的实现类),并把一个静态类User 的 name 和 经过加工的 password1 作为 用户名和密码。

image-20221014165121467

这正好对应了 前面登录时所需的用户名和密码。

但是这样的用户管理器很难满足真实业务需求,真实的用户数据存在于数据库中,因此可以重新构建 UserDetailsManager 的实现类 ,对功能进行扩展。

比如下面的 JdbcUserDetailsManager 。

JdbcUserDetailsManager

未完待续。。。


  1. Spring Security 提供了各种加密策略,密码前面需要添加{【加密类型】},例如:{noop}123, 表示没有加密。

daydream
1 声望0 粉丝

引用和评论

0 条评论