spring security
注:参考
动力节点课程
0. 基础知识
实现用户登录的两种方式
(1)基于session
总结:服务器端存session(含sessionID、用户信息)(session存在redis/mysql里),浏览器端存sessionID(存在cookie里),此后客户端每次请求都携带cookie,服务器从cookie里读取sessionID
(2)基于token
区别:服务器端无需存储token
补充:
安全框架两个关键:认证(判断一个人是否登录)+授权(判断一个人有无权限访问某资源)
1. 内存里的用户管理
1.1 创建配置类,利用manager生成用户
1.2 数据库中使用密文存储密码
关于加密算法,spring security推荐使用:
通过@Bean放到容器里就完事了
注:写单元测试的时候不要sout,要通过日志,可以输出更多线程啥的信息,@slf4j+log.info(something)
1.3 获取当前登录用户信息(获取认证信息)
如果用户认证登录成功,则信息放在Authentication类里
再把Authentication放到安全上下文SecurityContext里,因此也可以通过SecurityContext获取认证信息
至此完成了认证(登录控制,没登陆的人看不了东西),接下来实现授权(不同的人看不同的界面),将用户权限与url匹配
1.4 授权控制
1.4.1 url/controller级别的授权控制
通过配置类,写一个类来继承WebSecurityConfigurerAdapter,重写configure方法,注意重写的是针对HTTP协议(url)的configure函数
没有match的路径的表示只要登录了就能访问
1.4.2 方法级别的授权控制
不只控制controller层,也对service或更下层的方法进行访问控制
先在配置类中开启全局方法授权:
prePostEnabled
表示方法前/后进行授权拦截
在将进行拦截的方法前加注释,注释外的函数都能访问
1.5 前后端通过json传输数据(规范)
-
写各种处理器handler。配置认证成功/失败处理器,在此设置向前端返回的json
-
把处理器丢进完整的认证逻辑中
2. 与数据库结合
- 新建基础用户类实现UserDetails接口
- 新建类实现UserDetailService接口,里面只有一个方法:根据用户名获取用户信息
注:多对多的关系要转成三张表,比如一个人可以有多种角色,一类角色包含很多人,那么对应:人表,角色表,人id-角色id表
2.1 用户管理与数据库结合
(1)通过用户名,把用户信息从数据库中取出来
(2)自定义UserDetailsService,覆盖默认的
(3)实现UserDetails接口,自定义用户类
把从数据库中取出来的sysUser塞进自定义用户类MySecurityUser中,MySecurityUser一定要实现UserDetails接口
2.2 获取数据库中的权限并应用
实现这个方法:
上述转格式过程也可简化为stream流的方式
3. jwt
原来是通过session的方式,在服务器端要存大量数据,不好。
现在把数据封装到jwt(全称:json web token),存储在客户端
jwt(json web token)就是把各种信息(token的有效时间、用户信息等)进行封装,用json格式传输。
用户第一次登录,服务器给他一个jwt,此后用户每次访问服务器都带着这个token,服务器端每次处理请求时都要解码一下这个token,以此来知道是谁、哪个身份的人在向他发起请求。
总结:服务器端啥也不存,只负责校验就行,以前得18个用户对应18个session
生成jwt字符串(加密):
解密:
token作用:用户第一次登录验证成功后,服务器端生成token发给用户,此后用户向服务器端发起的请求都将携带token信息,用于后续调用一个服务器端请求时进行验证
用户登录成功,创建token并塞到对象里:
将handler加入到配置文件:
jwt的问题:不能修改。如果某个jwt时效一小时,但是用户半小时就下线了,因此与redis相结合
4. jwt+redis
登录成功,jwt加入到redis
用户退出,从redis中删除该token
利用spring注入redis,然后以键值对的形式放入redis
redis设置过期时间(与jwt有效时间一致)