SpringSecurity5.7.4从入门到精通全套教程
导读
什么是安全框架
SpringSecurity入门篇
SpringSecurity简介
1.快速入门,简单完成一个小案例
1.1准备工作
1.2创建访问接口:Controller类
1.3运行
2.知识点扩展
2.1登录校验流程
2.2SpringSecurity完整流程
2.3入门案例认证流程图
2.4SpringSecurity底层是一组过滤器
2.5 UserDetailService接口
2.6PasswordEncoder
本系列笔记仅供学习参考,希望能给大家带来提升和帮助
有不完善的地方欢迎评论指导,本人一定及时改正
导读
本系列笔记基于Spring Boot 2.7.5 + Java 8 + Spring Security 5.7.4版本,先从入门案例开始学会使用之后,在深入源码高效学习
什么是安全框架
开发软甲系统时,Web安全非常重要,Java安全框架,使用最多的是Spring Security、Apache Shiro
一个功能完善的安全框架,一般都需要支持以下特性,安全框架的底层是一批过滤器,原理大似相同,学会一个,其他的上手也很容易
认证(Authentication):验证用户的身份信息用户名和密码
授权(Authorization):验证用户的访问和权限,对已认证用户进行访问控制
加密:对重要信息进行加密处理,比如密码加密
会话管理:对用户认证、会话信息进行存储管理
防御攻击:对常见的网络攻击进行防御
SpringSecurity入门篇
SpringSecurity简介
SpringSecurity是Spring家族中的一个安全管理框架,相比另外一个安全框架Shiro,它提供了更丰富的功能,社区资源也比Shiro丰富。
一般来说中大型的项目基本使用的都是SpringSecurity来做安全框架,因为SpringSecurity属于Spring家族系列的,能够与Spring项目完美整合,小型项目有Shiro的比较多,因为Shiro是轻量级的安全认证框架,操作简单易上手。
一般Web应用的需要进行认证和授权
认证:SpringSecurity为身份验证提供了全面的支持,身份验证是验证进行访问的主体身份,常用方法是要求用户输入用户名(username)和密码(password),一旦执行身份验证,就知道身份并可以执行授权
授权:授权是指验证某个用户是否具有权限执行某个操作,在系统中不同用户所具有的权限是不同的,比如对淘宝商品信息来说,普通用户只能浏览,只有商家才能进行修改,一般系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限
认证和授权是SpringSecurity作为安全框架的核心功能
1.快速入门,简单完成一个小案例
1.1准备工作
首先要搭建SpringBoot工作,使用Spring Initializr快速创建一个SpringBoot项目,可以直接选择引入SpringSecurity依赖:
在SpringBoot项目中打开pom文件,修改SpringBoot的版本
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
导入开发所需要的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--SpringBoot提供的Security依赖场景-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--简化开发-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
spring-boot-starter-security是SpringBoot官方提供的启动器,提供了自动配置和依赖包管理
主要包含以下几个模块:
spring-security-core:核心包,包含核心认证和访问权限功能类和接口、远程支持和基本配置API
spring-security-web:WEB框架集成包,包含过滤器和相关的web安全基础设置代码
spring-security-config:包含security命名空间解析代码和Java配置代码
1.2创建访问接口:Controller类
@RestController<br>
public class SecurityController {
@GetMapping("/security")
public String welcomeToSecurityPage(){
return "欢迎学习Security,努力加油!";
}
}
1.3运行
启动程序,SpringBootSecurityApplication自动配置类,系统会自动生成一个默认的随机登录密码(因为当前没有配置用户信息,配置之后就不会在生成默认登录密码);
访问测试接口,此时被重定向到Security默认的登录页面:
用户名输入user,密码输入控制台生成的随机登录密码,登录成功后重定向到访问接口:
也可以在SpringBoot的配置文件application.yml中配置一个默认的登录用户和密码(了解就行)
spring: security: user: name: jack password: 123456
这样就完成了入门案例,上手操作非常简单,因为认证和授权的过程都被SpringSecurity底层给我们做了。
下面我们需要深入了解SpringSecurity相关知识,熟悉掌握SpringSecurity
2.知识点扩展
2.1登录校验流程
2.2SpringSecurity完整流程
SpringSecurity的原理其实就是一个过滤器链,内部包含了提供各种功能的过滤器。这里我们可以看看入门案例中的过滤器
图中只展示了核心过滤器,其他非核心的过滤器并没有在图中展示
UsernamePasswordAuthenticationFilter:负责处理我们在登录页面填写了用户名和密码后的登录请求,入门案例的认证工作主要有它负责
ExceptionTranslationFilter:异常过滤器,处理过滤器链中抛出的任何AccessDeniedException和AuthenticationException。
FilterSecurityInterceptor:负责权限校验的过滤器,最底层的过滤器,真正的调用后台服务
2.3入门案例认证流程图
这个只是入门案例的流程图,不求记住大致做个了结就行,知道运行过程,后面我们自定义开发自己的配置
2.4SpringSecurity底层是一组过滤器
在Spring Security中,认证、授权等功能都是基于过滤器来完成的,下列为Spring Security中常见的过滤器,混个眼熟
以上过滤器是否默认加载是指引入Spring Security依赖之后,开发者不做任何配置时,会自动加载的过滤器
2.5 UserDetailService接口
当什么也没有配置的时候,账号和密码是由SpringSecurity定义生成,而在实际开发中账号和密码都是从数据库中查询出来,所以我们要通过自定义逻辑控制认证逻辑
总结:查询数据库用户名和密码的过程
创建类继承UsernamePasswordAuthenticationFilter,重写三个方法 attemptAuthentication successfulAuthentication unsuccessfulAuthentication 创建类实现UserDetailService。编写查询数据过程,返回User对象,这个User对象是安全框架提供的对象
//UseDetailService接口
public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
//自定义实现类实现UserDetailService接口
@Service
public class UserDetailServiceImpl implements UserDetailsService {
@Autowired
UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//查询用户信息
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getUserName,username);
User user = userMapper.selectOne(queryWrapper);
//如果没有查询到用户就抛出异常
if (Objects.isNull(user)){
throw new UsernameNotFoundException("查无该用户,请重试");
}
//TODO 查询对应的权限信息
return new LoginUser(user);
}
}
2.6PasswordEncoder 数据加密接口,用于返回User对象里面的密码加密
public interface PasswordEncoder {
//表示把参数按照特定的解析规则进行解析
String encode(CharSequence rawPassword);
//表示验证从存储中获取的编码密码与编码后提交的原始密码是否匹配,如果
//密码匹配,则返回true;如果不匹配;则返回false,第一个参数表示需要
//被解析的密码,第二个参数表示存储的密码
boolean matches(CharSequence rawPassword, String encodedPassword);
//表示如果解析的密码能够再次进行解析且达到更安全的结果则返回true
//否则返回false,默认返回false
default boolean upgradeEncoding(String encodedPassword) {
return false;
}
}
接口实现类:
BCryptPasswordEncoder是SpringSecurity官方推荐的密码解析器,平时多使用这个解析器
BCryptPasswordEncoder是基于Hash算法实现的单向加密,可以通过strength控制加密强度,默认10
方法实例演示
@Test
public void test01() {
// 创建密码解析器
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
// 对密码进行加密
String password= bCryptPasswordEncoder.encode("password");
// 打印加密之后的数据
System.out.println("加密之后数据:\t" + password);
//判断原字符加密后和加密之前是否匹配
boolean result = bCryptPasswordEncoder.matches("password", password);
// 打印比较结果
System.out.println("比较结果:\t" + result);
}
开发者所见到的Spring Security提供的功能,都是通过这些过滤器实现的,这些过滤器按照既定的优先级排列,最终形成一个过滤器链,开发者也可以自定义过滤器,并通过==@Order==注解去调整自定义过滤器在过滤器链中的位置
需要注意的是,默认过滤器并不是直接放在Web项目的原生过滤器中,而是通过一个FilterChainProxy来统一管理,Spring Security中的过滤器链通过FilterChainProxy嵌入到Web项目的原生过滤器链中