SpringSecurity快速入门
SpringSecurity快速入门
1.简介
Spring Security 是Spring 家族中的一个安全管理框架。相比与另外一个安全框架Shiro,它提供了更丰富的功能,社区资源也比Shiro丰富。
一般来说中大型的项目都是使用SpringSecurity来做安全框架。小项目有Shiro的比较多,因为相比与SpringSecurity, Shiro的上手更加的简单。
一般Web应用的需要进行认证和授权。
认证:验证当前访问系统的是不是本系统的用户,并且要确认具体是哪个用户
授权:经过认证后判断当前用户是否有权限进行某个操作
而认证和授权也是SpringSecurity作为安全框架的核心功能。
2.快速上手
pom.xml 中的 Spring Security 依赖:
1 | <dependency> |
只要加入依赖,项目的所有接口都会被自动保护起来。
引入依赖后我们在尝试去访问之前的接口就会自动跳转到一个SpringSecurity的默认登陆页面,默认用户名是user,密码会在控制台输出
3.认证
3.1 登录校验过程
3.2 SpringSecurity 认证流程
SpringSecurity的原理其实就是一个过滤器链,内部包含了提供各种功能的过滤器。这里我们可以看看入门案例中的过滤器。
UsernamePasswordAuthenticationFilter:负责处理我们在登陆页面填写了用户名密码后的登陆请求。入门案例的认证工作主要由它负责。
ExceptionTranslationFilter: 处理过器链中抛出的任何AccessDeniedException和AuthenticationException。
FilterSecuritylnterceptor:负责权限校验的过滤器。
我们可以通过Debug查看当前系统中SpringSecurity过滤器链中有哪些过滤器及它们的顺序。
认证流程图:
3.3 思路
登录
①自定义登录接口
调用ProviderManager的方法进行认证如果认证通过生成jwt
把用户信息存入redis中
②自定义UserDetailsService
在这个实现列中去查询数据库
校验:
①定义Jwt认证过滤器
获取token
解析token获取其中的userid
从redis中获取用户信息
存入SecurityContextHolder
1、严格来说,使用jwt是不用redis的,因为jwt初衷就是为了无状态,你加上redis,就违背了初衷,这也是网上对jwt最为诟病的一个地方。
2、使用redis并不是为了减轻数据库的压力,因为jwt本身是可以在payload中放入一些用户基本信息的,在前端携带token访问时,对token进行解析,可以获取到这些数据并写入SecurityContextHolder当中,这样在后面的处理当中,都可以获取到当前用户的相关信息。
3、由于jwt的无状态,后端是没法感知和控制用户的在线状态的,所以加入了redis这一层,在校验token的同时检查redis相关状态从而实现后端对用户状态的控制。
4、所以对于无状态应用,jwt是再好不过的一个东西,但是对于我们常见的有状态应用,使用一个uuid也是能达到相同的效果的。
自定义UserDetailsService
1 |
|
3.4密码加密存储
实际项目中我们不会把密码明文存储在数据库中。
默认使用的PasswordEncoder要求数据库中的密码格式为:(idypassword。它会根据id去判断密码的加密方式。但是我们一般不会采用这种方式。所以就需要替换PasswordEncoder。|
我们一般使用SpringSecurity为我们提供的BCryptPasswordEncoder.
我们只需要使用把BCryptPasswordEncoder对象注入Spring容器中,SpringSecurity就会使用该PasswordEncoder来进行密码校验。
我们可以定义一个SpringSecurity的配置类, SpringSecurity要求这个配置类要继承WebSecurityConfigurerAdapter。
1 |
|
测试:
1 | @ Test |
结果:
1 | $2a$10$bFOw3cFWQ93RDQo.hODJL.sgYMXRMRdQk5u2bCDf4xItNz/1Y jFn6 |
$2a$10$ + 盐(22位) + 密文