学习介绍
网上关于SpringSecurity的教程大部分都停留在6以前的版本 但是,SpringSecurity6.x版本后的内容进行大量的整改,网上的教程已经不能够满足 最新的版本使用。这里我查看了很多教程 发现一个宝藏课程,并且博主也出了一个关于SpringSecurity的权限认证的项目,前后端都有。且免费
哔站最好的SpringSecurity6讲解课程 以及三更草堂的SpringSecurity讲解 只不过版本不同。按需观看
认证流程
登录流程
我们来回想一下开始学习开发的时候如何做到一个登录校验的过程,这边以图解形式展示。
那么,在一些权限管理系统中 使用这种认证操作就会比较难以实现功能,
比如说我此时会员用户和普通用户 需要有不同的功能权限,依靠一个拦截器的情况下很难说实现。
此时就需要使用到springSecurity进行校验,SpringSecurity其中是一个过滤器链 对角色和权限认证提供了很好的对应接口。
SpringSecurity认证流程
这个图片是 哔站三更草堂 的授课资料中的,如果想要学习SpringSecurity5版本的可以去看这个内容,这张图现在是看不明白的,先记一下下面的基础概念。这部分内容分别是什么。
概念速查:
Authentication接口: 它的实现类,表示当前访问系统的用户,封装了用户相关信息。
AuthenticationManager接口:定义了认证Authentication的方法
UserDetailsService接口:加载用户特定数据的核心接口。里面定义了一个根据用户名查询用户信息的
方法。
UserDetails接口:提供核心用户信息。通过UserDetailsService根据用户名获取处理的用户信息要封装
成UserDetails对象返回。然后将这些信息封装到Authentication对象中
引入SpringSecurity依赖
SpringSecurity也是Spring框架中的一种,所以他仍然需要依靠于Spring框架才能发挥作用
SpringSecurity maven坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
此时我们使用浏览器访问一些自定义接口的时候会发现,多了一个校验内容,会跳转到一个登录界面,此时SpringSecurity就创建成功了,账号admin 密码会在控制台输出,现在我们可以进行下一步配置。
yml文件修改默认用户和密码
在Application.yml文件中初始化Security的账户和密码,配置重启项目 控制台就不会输出这个密码了
spring:
security:
user:
name: admin
password: 123456
roles: ['admin','user']
其中这个配置文件生效的流程 主要是在SecurityProperties类中做了初始化的内容。
SpringSecurity配置类
这个配置类跟6之前版本的差别还是挺大的,6版本的配置类变成了依靠注解的形式进行定义。想要更改默认配置就自己重新注入对应的配置内容。这边我主要书写一下一部分配置的内容 标以注释的形式
@Configuration
// 这个注解的作用是标记一个Security类 启用SpringSecurity的自定义配置
@EnableWebSecurity
// 启用方法注解认证
@EnableMethodSecurity
public class SecurityConfig {
/*
* 基本配置讲解
* */
// 自定义用户名和密码 初始
// 一般替换成 自定义userDetailsService
@Bean
public UserDetailsService userDetailsService() {
// 密 码 : 1234
UserDetails build = User.withUsername("zhangsan")
.password("$2a$10$L5xB2VxwKM2kQL4SMTBdyej8e4VpfeMP3XF1660weV0n.WGRbsXdC")
// .password("{noop}1234")
// 基础无加密的密码需要再前面跟上{noop}这个内容
// 角色的创建
.roles("admin").build();
UserDetails build1 = User.withUsername("user")
.password("$2a$10$L5xB2VxwKM2kQL4SMTBdyej8e4VpfeMP3XF1660weV0n.WGRbsXdC")
.roles("user").build();
//这个是基于内容的储存校验
InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
inMemoryUserDetailsManager.createUser(build);
inMemoryUserDetailsManager.createUser(build1);
return inMemoryUserDetailsManager;
}
}
过滤器链
这个位置的书写 都写成lambda表达式了 和之前的不一致
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// 关闭csrf机制
http.csrf(csrf->csrf.disable());
// 在user下面的所有路径下 都不进行验证 其他的页面进行权限认证
http.authorizeHttpRequests(auth->auth.requestMatchers("/user/**")
.permitAll().anyRequest().authenticated());
return http.build();
}
密码处理
一般以BCryptPasswordEncoder工具进行处理密码的内容,但是需要注意此时的时候你的初始密码必须是BCryptPasswordEncoder加密的内容
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
授权
用户认证之后,会去存储用户对应的权限,并且给资源设置对应的权限,SpringSecurity支持两种粒度
的权限
基于请求的:在配置文件中配置路径,可以使用**的通配符
基于方法的:在方法上使用注解实现
动态权限:用户权限被修改之后,不需要用户退出,会自动刷新,也不需要修改代码
UserDetails build = User.withUsername("zhangsan")
.password("$2a$10$L5xB2VxwKM2kQL4SMTBdyej8e4VpfeMP3XF1660weV0n.WGRbsXdC")
// .password("{noop}1234")
// 基础无加密的密码需要再前面跟上{noop}这个内容
// 角色的创建
.roles("admin")
.authorities("test1:show")
.build();
进行授权authorities后需要加入A:B的这种形式
对请求中进行鉴权过滤
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// 配置关闭csrf机制,
http.csrf(csrf -> csrf.disable());
// 配置请求拦截方式
// requestMatchers() : 匹配资源路径
// permitAll() :随意访问
// anyRequest():其他任意请求
// authenticated() : 需要认证之后
http.authorizeHttpRequests(auth ->
// auth.requestMatchers("/test1").hasRole("admin")
// auth.requestMatchers("/test1").hasAnyRole("admin", "user")
// auth.requestMatchers("/test1").hasAuthority("test1:show")
// 这个位置进行的路径鉴权 - 那一部分路径使用权限认证 那一部分不使用
auth.requestMatchers("/test1").hasAnyAuthority("test1:show", "user:show")
.requestMatchers("/to_login").permitAll()
.anyRequest().authenticated());
);
return http.build();
}