一. spring security 的概述
Spring Security 是 Spring 家族中的一个安全管理框架,是Spring采用AOP思想,基于servlet过滤器实现的安全框架。一般Web应用的需要进行认证和授权。而 认证(验证当前访问系统的是不是本系统的用户,并且要确认具体是哪个用户) 和 授权(经过认证后判断当前用户是否有权限进行某个操作) 也是SpringSecurity作为安全框架的核心功能。
1. 认证
1.1 完整流程
Security原理其实就是一个过滤器链,内部包含了提供各种功能的过滤器。通过Debug查看当前系统中SpringSecurity过滤器链中有哪些过滤器及它们的顺序。(展示核心过滤器)
UsernamePasswordAuthenticationFilter: 负责处理我们在登陆页面填写了用户名密码后的登陆请求。入门案例的认证工作主要有它负责。
ExceptionTranslationFilter: 处理过滤器链中抛出的任何AccessDeniedException和AuthenticationException 。
FilterSecurityInterceptor: 负责权限校验的过滤器。
1.2 登录校验流程
1.3 认证流程详解
Authentication接口: 它的实现类,表示当前访问系统的用户,封装了用户相关信息。
AuthenticationManager接口:定义了认证Authentication的方法
UserDetailsService接口:加载用户特定数据的核心接口。里面定义了一个根据用户名查询用户信息的方法。
UserDetails接口:提供核心用户信息。通过UserDetailsService根据用户名获取处理的用户信息要封装成UserDetails对象返回。然后将这些信息封装到Authentication对象中。
2. 授权
2.1 授权基本流程
Security中会使用默认的FilterSecurityInterceptor进行权限校验。FilterSecurityInterceptor中会从SecurityContextHolder获取其中的Authentication,然后获取权限信息。当前用户是否拥有访问当前资源所需的权限。所以在项目中只要把当前登录用户的权限信息存入Authentication。然后设置我们的资源所需要的权限即可。
2.2 RBAC权限模型
RBAC权限模型(Role-Based Access Control)即:基于角色的权限控制。这是目前最常被开发者使用也是相对易用、通用权限模型。
3. 自定义失败处理
在SpringSecurity中,如果认证或授权的过程中出现异常会被ExceptionTranslationFilter捕获到。在ExceptionTranslationFilter中会去判断是认证失败还是授权失败出现的异常。如果是认证过程中出现的异常会被封装成AuthenticationException然后调用AuthenticationEntryPoint 对象的方法去进行异常处理。如果是授权过程中出现的异常会被封装成AccessDeniedException然后调用AccessDeniedHandler对象的方法去进行异常处理。所以如果我们需要自定义异常处理,我们只需要自定义AuthenticationEntryPoint和AccessDeniedHandler然后配置给SpringSecurity即可。
4. 跨域
浏览器出于安全的考虑,使用 XMLHttpRequest对象发起 HTTP请求时必须遵守同源策略,否则就是跨域的HTTP请求,默认情况下是被禁止的。 同源策略要求源相同才能正常进行通信,即协议、域名、端口号都完全一致。前后端分离项目,前端项目和后端项目一般都不是同源的,所以肯定会存在跨域请求的问题。所以我们就要处理一下,让前端能进行跨域请求。
二. 快速入门
搭建一个简单的SpringBoot工程,添加依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.0</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
创建启动类
@SpringBootApplication
public class SecurityApplication {
public static void main(String[] args) {
SpringApplication.run(SecurityApplication.class,args);
}
}
创建Controller
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
return "hello";
}
}
引入SpringSecurity
引入依赖后我们在尝试去访问之前的接口就会自动跳转到一个SpringSecurity的默认登陆页面,默认用户名是user,密码会输出在控制台。必须登陆之后才能对接口进行访问。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>