快速搭建完springboot的CURD,还缺一个登录接口
这里我还是推荐一下 B站的视频 https://www.bilibili.com/video/BV1mm4y1X7Hc 三更草堂的视频还不错,从原理讲到实操。
内容比较多,仅仅登录部分合起来就要2个多小时。
这里是我搜到的某位的学习源码部分
https://gitee.com/misszyg/spring-security
我呢,是接着上一期的curd去写的,因为controller 和 表 都能复用,外加操作数据库不多就JPA用着也行
首先要做的准备工作是 pom.xml引入 Springboot Security&JWT&Redis 这三个的依赖,如果redis不是本机需要去配置一下
项目跑起来后呢就,Springboot Security内置了不分离的页面登录。
第一步 替换比对用户的数据源
默认的实现是不分离的,从内存中拿生成用户信息比对。
所以首先要重新实现获取用户的方法,实现从数据库中取用户。
这里是要重写Security中UserDetailsService接口的loadUserByUsername方法,返回类型是UserDetails
方法里面就是从数据库中取出user,根据要求返回类型是UserDetails,我们需要建一个实体类LoginUser去实现UserDetails,并且把user包装成UserDetails实体类的对象进行返回。这一步做完就是能用数据中的数据来校验登录了。
第二步 是写登录接口
写接口之前呢,先要写一个Springboot Security配置类,作用是两个,把默认的加解密算法替换掉,另外就是配置对登录接口,要在未认证的情况下可以访问
controller中/login 接口方法就是去服务中调用方法,内部是调用Springboot Security的 authenticationManager.authenticate
方法,把传进去的user包装成authenticationToken对象传参进去,返回非空authentication对象成功,authentication.getPrincipal获得LoginUser对象 ,然后拿到userid去用jwt加密成token传返回,并且把loginuser的信息以userid复合字符串为key存redies,
这一步完成就可以向/login post用户名和密码获取token了,这里的小提示呢,是先要了解一下jwt 和 redis缓存,需要写两个工具类,另外User实体类 需要继承可序列化接口,因为存redis需要LoginUser对象可序列化。
第三步 写一个Springboot Security的过滤器JwtAuthenticationTokenFilter
因为Springboot Security本身就有过滤器链,还可以在源码中查看他们的顺序十几个呢,这个过滤器的作用呢,就是当一个请求过来,去获取header的token,如果没有token就放行等后面的过滤器收拾,如果有呢,就jwt解密,并从Redis取loginUser数据,这里解密和取数据不一定总成功,会抛出认证异常,这里依然是把取出的loginUser包装成authenticationToken传入SecurityContextHolder更改认证状态,并保证后面过滤器能从这里取得验证认证状态及用户信息,所以还要在Springboot Security配置类里给它在过滤器链里配置一个不能太后的位置,ExceptionTransationFilter的后面,这一步写完呢,基本登陆就写完了。
最后呢,完善一下登出操作,controller中开辟一个logout接口,在服务方法中直接从SecurityContextHolder取出登陆的用户信息,然后通过redis删除用户信息缓存即可.
这里标红的部分是过滤器中的异常,这些异常按顺序而言并不会被@RestControllerAdvice注解捕获处理,所以过滤器中的异常类型,要设置成Springboot Security里过滤器里面的异常类型,并在Springboot Security配置类中统一处理,当然也要配置这个本过滤器的位置不能太前,要在Springboot Security过滤链的异常处理过滤器ExceptionTransationFilter的后面,这样过滤器抛出的异常就会在回链经过ExceptionTransationFilter时候得到处理。
代码链接:https://gitee.com/zskj/springboot_security_demo