简介
Spring Security 是一个功能强大且高度可定制的身份验证和访问控制框架。
在安全框架中,我们最常提到的两个概念是“认证”和“授权”(或者访问控制)。这两个主要区域是Spring Security 的两个目标。“认证”,是建立一个他声明的主题的过程(一个“主体(Subject)”一般是指用户,设备或一些可以在你的应用程序中执行动作的其他系统)。“授权”指确定一个主体是否允许在你的应用程序执行一个动作的过程。为了抵达需要授权的店,主体的身份已经有认证过程建立。
简单入门
- 设置父工程 添加依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
- 创建启动类
@SpringBootApplication
public class SecurityApplication {
public static void main(String[] args) {
SpringApplication.run(SecurityApplication.class);
}
}
- 创建Controller
@RestController
public class DemoController {
@RequestMapping("/")
public String index() {
return "hello security";
}
}
项目启动成功后,当尝试去通过浏览器访问项目接口的时候,会自动跳转到一个SpringSecurity的默认登陆页面,默认用户名是user,密码会打印在控制台上。
这个就是spring-security框架产生安全拦截效果了,spring-security在spring-boot的项目框架中自动配置了规则和策略。
必须登录之后才能对接口进行访问。
认证
现在的项目大部分都采用了前后端分离的架构设计。这种架构也会导致权限设计方面有所改变。
登录校验流程
原理解读
认证流程
Spring Security维护着一个过滤器链,每个过滤器都有一个特定的责任和过滤器中添加或删除的配置取决于哪些服务是必需的。过滤器的顺序很重要,因为它们之间有依赖关系。
重点且必须了解的过滤器:
- UsernamePasswordAuthenticationFilter: 该过滤器会拦截前端提交的POST方式的登录表单请求,并进行身份认证。
- ExceptionTranslationFilter: 该过滤器不需要我们配置,对于前端提交的请求会直接放行,捕获后续到响应前抛出的异常并进行处理(例如:权限访问限制)
- FilterSecurityInterceptor: 该过滤器是过滤器链的最后一个过滤器,根据资源权限配置来判断当前请求是否由ExceptionTranslationFilter 过滤器进行捕获和处理。
Authentication接口:它的实现类,表示当前访问系统的用户,封装了用户相关信息。
AuthenticationManager接口:定义了认证Authentication的方法
UserDetailsService接口:加载用户特定数据的核心接口。里面定义了一个根据用户名查询用户信息的方法。
UserDetails接口:提供核心用户信息。通过UserDetailsService根据用户名获取处理的用户信息要封装成UserDetails对象返回。然后将这些信息封装Authentication对象中.
登录
- 自定义登录接口
调用ProviderManager的方法进行认证 如果认证通过生存jwt
把用户信息存入redis中 - 自定义UserDetailsService
在这个实现列中去查询数据库
校验:
- 定义JWT认证过滤器
获取token
解析token获取其中的userid
从redis中获取用户信息
存入SecurityContextHolder
授权
简而言之就是让不通的登录用户能够使用不同的功能权限。
授权基本流程
在SpringSecurity中,会使用默认的FilterSecurityInterceptor来进行校验,在FilterSecurityInterceptor中会从SecurityContextHolder获取其中的Authentication,然后获取其中的权限信息,当前用户是否拥有访问当前资源所需的权限。
所以我们在项目中只需要把当前登录用户的权限信息也存入 Authentication。
然后设置我们的资源所需要的权限即可。
授权实现
限制访问资源所需的权限
SpringSecurity为我们提供了基于注解的权限控制方案,这也是我们项目中主要采用的方式。
在使用该功能之前还需要先开启相关配置
@EnableGlobalMethodSecurity(prePostEnabled = true)
然后就可以使用对应的注解。@PreAuthorize
@RestController
public class DemoController {
@RequestMapping("/")
@PreAuthorize("hasAnyAuthority('test')")
public String index() {
return "hello security";
}
}