初学Spring security+Jwt鉴权流程

2022-08-05 13:06:48

具体环节如下:

1.引入相关依赖(包含spring-security,mybatis-plus,mysql,jwt,lombok这几个需要用到的)

!注意:这是我们需要去添加的,还有一些其他的在建springboot-web工程的时候就默认创建了

2.接着配置数据库连接,这个根据大家具体的数据库和用户密码设置,这里也提供简单参考

3.需要两个实体类,一个实体类对应数据表的各个属性,另一个实体类负责实现UserDetails类封装一个对象用于在整个认证框架中传递(因为我们想要封装的这个对象里肯定也要涉及到数据表里的各个属性,故把前面创建的负责映射数据表的实体类注入进来,这里提供一个简单的例子,Book负责关联数据表,MyUserDetails负责封装我们想在框架里传的那个类)

 !注意:基本上的方法都是直接implement出来的,我们需要做的就是注入自己的对象,添加有参无参构造注解,然后修改getPassword和getUsername两个方法的返回值(即告诉框架你的哪两个字段为用户密码,我这边随便拿的一张表,就用type当用户名,name当密码了),最后所有boolen类型改为true

4.接着我们要去实现对数据库的增删改查,因为你识别用户名和密码的时候肯定要用到,我这里是使用了mybatis-plus就很简单了

 5.接着我们创建一个类去实现UserDetailsService(这一个类相当于修改框架,让他按照我们自己的规则去识别用户名密码,这里我们肯定是想要去查数据库看看是否存在匹配的用户名密码,没有的话输出个异常,有的话把查到的信息封装成对象返回框架,因为框架对于对象的识别有特别的要求,故我们之前创建用来封装的实体类就派上了用场,具体如下)

 !注意:不好理解这一步的话大家可以想象整个识别过程都是框架替我们完成的,而框架默认的识别方式我们不适用所以替换成了自己的,其他的部分不冲突故继续使用,而之所以能够用自定义的实体类去返回是因为我们前面写这个类的时候就是implement框架中的类实现的,所以框架能够识别的到

6.框架部分改好之后,我们写一下控制类,以及对控制类的实现,这些就是常规操作了不涉及到框架问题(简单说一下就是控制类中定义提交入口和方式,注入实现类的接口,调用自己实现类的方法,这一步先把这个壳先建出来,具体实现方法第7步介绍)

 7.接着我们可以想一下实现类中具体要做什么(大致就是我们要告诉框架从页面上或者说前端获取到的账号密码是什么,然后让框架去执行它自己的那一套流程,最后告诉我们这个人在数据库中有没有,有的话我们生成jwt令牌,故这里我们就需要自定义一个jwt的工具类,这边也给大家提供了一个最简单的版本,分别是生成jwt和解析jwt,解析后面鉴权才用)

 !注意:jwt工具类没什么好说的,可能有人对login实现类中的方法不好理解,这里简单介绍一下。(首先大家记住这可以算一个偏固定的写法,大家先知道要去这样写)具体来说就是我们获取到页面上传来的对象后,框架为我们提供了一个authenticate方法,以便识别我们的用户名密码,而这个方法只能由框架中的anthenticationManager来调用,所以我们需要把anthenticationManager注入进来(报错先不管)。然后我们使用authenticate方法的时候发现参数也有特定的要求,好在框架也提供了相应的对象用来存我们的信息(即UsernamePasswordAuthenticationToken),我们把账号密码存到这个对象里然后再把这个对象作为参数传给authenticate就可以了。最后如果识别返回为空输出错误,否则把传回来的值取出来调用工具类创建 jwt。

8.这时候我们来解决第7步中anthenticationManager注入报错问题。创建一个类继承框架中的WebScurityConfigurerAdapter,然后重写authenticationManagerBean方法(注意这里是固定格式记住就好,相当于框架中有authenticationManager但你的Spring容器不知道,所以你要把它写出来@bean给Spring容器注入时才会识别的到)

 !注意:我们继承的WebScurityConfigurerAdapter这个类大家可以理解成对Spring-Security框架的一个全局配置,后面我们有涉及框架整体的配置都在这设置,这一部分没什么好理解的方式,记住就好。

9.前8步我们相当于已经可以识别数据库中是否有我们输入的用户并在有的时候传回jwt令牌(给前端页面并进行存储),那我们接下来要做的就是在用户进行后续操作的时候对jwt令牌进行解析与放行,这边采用的是过滤器写法,相对也比较模板化(具体就是我们创建jwt令牌的时候已经将用户名,用户密码,用户权限携带加密进去了,现在只需要把令牌拿过来调用解析方法取到用户信息,通过SecurityContextHolder.getContext().setAuthentication()方法告诉框架即可)

!注意:这里要小心的就是 UsernamePasswordAuthenticationToken对象中第三个参数得是特定类型的list集合,我们这里采用SimpleGrantedAuthority类型,并且其实这里抛不抛异常都无所谓了,如果查不到在前几个阶段就扔异常结束了

10.现在我们完善一下对整体框架的配置(即前面用来继承WebScurityConfigurerAdapter的那个类),其实就是要把我们自己写的这个过滤器加入到框架中

 !注意:可能有些人不懂为什么加在UsernamePasswordAuthenticationFilter之前,大家可以回头看下第9步中我们如果解析到了用户信息,是通过UsernamePasswordAuthenticationToken告诉框架的,意味着这个过滤器是先于UsernamePassword执行的

11.到此操作基本都完成了,分配权限相对就比较简单了(首先在控制类中不同请求前添加@preauthorize(“hasauthority(XX)”)注解,XX为不同的权限,接着在对框架的配置中添加@enableglobalmethodsecurity(prepostenabled=true)注解并做一些完善),这里也简单提供一个例子,都是比较固定的操作了,细心就好

 总结:到此,整个认证,鉴权的流程就结束了,具体开发中必然还要做一些特定的修改,但刚开始学习这一块可以以此参考学习!!!

补充:我这边用的是postman接口测试,是分开测试jwt令牌生成和权限识别,所以没有把jwt令牌传回前端,如果大家要做完整的一套流程,记得login方法那边不要用void,改成其他类型传回前端就好啦。

  • 作者:偏执的胖纸
  • 原文链接:https://blog.csdn.net/weixin_44152952/article/details/124115458
    更新时间:2022-08-05 13:06:48