七叶笔记 » java编程 » Spring Security+JWT实现认证与授权的实现

Spring Security+JWT实现认证与授权的实现

认证:验证当前访问系统的是不是本系统的用户,并且要确认具体是哪个用户

授权:经过认证后判断当前用户是否有权限进行某个操作

一、登录校验流程

1、Spring Security 完整流程

SpringSecurity的原理其实就是一个过滤器链,内部包含了提供各种功能的过滤器。部分核心过滤器如下图:

UsernamePasswordAuthenticationFilter:负责处理在登录页填写了用户名密码后的登陆请求。

ExceptionTranslationFilter:处理过滤器链中抛出的任何AccessDeniedException(访问出错)和AuthenticationExcption(认证出错)。

FilterSecurityInterceptor:负责权限校验的过滤器。

2、Spring Security的默认登陆验证流程。

Authentication接口:它的实现类,表示当前访问系统的用户,封装了用户相关信息。

AuthenticationManager接口:定义了认证Authentication的方法。

UserDetailsService接口:加载用户特定数据的核心接口。里面定义了一个根据用户名查询用户信息的方法。

UserDetails接口:提供核心用户信息。通过UserDetailsService根据用户名获取处理的用户信息要封装成UserDetails对象返回。然后将这些信息封装到Authentication对象中。

3、 整合JWT大致流程

登录

        ①自定义登录接口

                调用ProviderManager的方法进行认证 如果认证通过生成JWT。

                把用户信息存入redis中        

        ②自定义UserDetailsService

                在这个实现类中去查询数据库

校验

        ①定义Jwt认证过滤器

        获取token

        解析token获取其中的userid

        从redis中获取用户信息

        存入SecurityContextHolder

Redis使用Fastjson序列化

前端响应类

JWT工具类

创建数据库表信息和实体,配置数据库连接信息

定义mapper等一系列接口。xml等。用mybatis-plus方便一点,注意Mapper继承BaseMapper<实体类>,实体类中需要加@TableName(value = "表名") ,id字段上加 @TableId

在application.yml中配置mapperXML文件的位置

引入依赖

重写UserDetailsService的方法

创建一个类实现UserDetailsService接口,重写其中的方法。从数据库中查询用户信息,进行校验。(如果没有重写的话,就是上面说的spring security默认的使用UserDetailsService接口下面的InMemoryUserDetailsManager实现类中的方法,是在内存中查找。这个是需要根据我们具体的系统来重写的。)

因为UserDetailsService方法的返回值是UserDetails类型,所以需要定义一个类,实现该接口,把用户信息封装在其中。

重写登录接口

        接下我们需要自定义登陆接口,然后让SpringSecurity对这个接口放行,让用户访问这个接口的时候不用登录也能访问。

在接口中我们通过AuthenticationManager的authenticate方法来进行用户认证,所以需要在SecurityConfig中配置把AuthenticationManager注入容器。

认证成功的话要生成一个jwt,放入响应中返回。并且为了让用户下回请求时能通过jwt识别出具体

的是哪个用户,我们需要把用户信息存入redis,可以把用户id作为key。

认证过滤器

我们需要自定义一个过滤器,这个过滤器会去获取请求头中的token,对token进行解析取出其中的userid。(把这个放到最前面,放到UsernamePassword的那个前面)这样做就是为了除了登录的时候去查询数据库外,其他时候都用JWT配合Redis进行认证。

使用userid去redis中获取对应的LoginUser对象。

然后封装Authentication对象存入SecurityContextHolder

退出登陆

        我们只需要定义一个登陆接口,然后获取SecurityContextHolder中的认证信息,删除redis中对应的数据即可。

授权基本流程

        在SpringSecurity中,会使用默认的FilterSecurityInterceptor来进行权限校验。在FilterSecurityInterceptor中会从SecurityContextHolder获取其中的Authentication,然后获取其中的权限信息。当前用户是否拥有访问当前资源所需的权限。

所以我们在项目中只需要把当前登录用户的权限信息也存入Authentication。

然后设置我们的资源所需要的权限即可。

限制访问资源所需权限

        SpringSecurity为我们提供了基于注解的权限控制方案,这也是我们项目中主要采用的方式。我们可以使用注解去指定访问对应的资源所需的权限。

        但是要使用它我们需要先开启相关配置。

        然后就可以使用对应的注解。@PreAuthorize  

封装权限信息

我们前面在写UserDetailsServiceImpl的时候说过,在查询出用户后还要获取对应的权限信息,封装到UserDetails中返回。

RBAC权限模型

RBAC权限模型(Role-Based Access Control)即:基于角色的权限控制。这是目前最常被开发者使用也是相对易用、通用权限模型。

 参考表:

查询条件

自定义失败处理

我们还希望在认证失败或者是授权失败的情况下也能和我们的接口一样返回相同结构的json,这样可以让前端能对响应进行统一的处理。要实现这个功能我们需要知道SpringSecurity的异常处理机制。

在SpringSecurity中,如果我们在认证或者授权的过程中出现了异常会被ExceptionTranslationFilter捕获到。在ExceptionTranslationFilter中会去判断是认证失败还是授权失败出现的异常。

如果是认证过程中出现的异常会被封装成AuthenticationException然后调用AuthenticationEntryPoint对象的方法去进行异常处理。

如果是授权过程中出现的异常会被封装成AccessDeniedException然后调用AccessDeniedHandler对象的方法去进行异常处理。

所以如果我们需要自定义异常处理,我们只需要自定义AuthenticationEntryPoint和AccessDeniedHandler然后配置给SpringSecurity即可。

配置给SpringSecurity

到此这篇关于Spring Security+JWT实现认证与授权的实现的文章就介绍到这了,更多相关Spring Security JWT认证与授权内容请搜索七叶笔记以前的文章或继续浏览下面的相关文章希望大家以后多多支持七叶笔记!

相关文章