【框架】参考 Spring Security 安全框架设计出,轻量化高可扩展的身份认证与授权架构

关键字:AOP、JWT、自定义注解、责任链模式

一、Spring Security

Spring Security 想必大家并不陌生,是 Spring 家族里的一个安全框架,特别完善,但学习成本比较大,不少开发者都觉得,这个框架"很重"

他的认证授权的过程时使用的 api 和组件比较复杂,但这不是主要的顾虑

并且,他是基于过滤器实现的,其过程抛出的异常并不会被全局异常处理器拦截,通过 SpringSecurity 认证授权的请求,才算进入我们的 Spring 环境下

但不得不说他确实有优点

  1. 对请求的一个 AOP 的统一处理(但是好像没有专门的后置处理器)
  2. 可以通过添加过滤器的方式增加认证过程,也对某些路由可添加授权过程
  3. 框架的一些注解,例如 @PreAuthorize,可以很方便的进行接口权限的设置

虽然它封装了很多现成的东西,但其实一些自己去写也没什么大不了的,还可以按照自己的想法去定制

我们可以学习它的优点去优化一下我们原本的认证授权架构

二、AOP + JWT

通过全局拦截器,拦截所有的请求,请求携带访问令牌 JWT,这里就不必多说了

三、自定义注解

自定义一个可以 Retention 为 Runtime,Target 为 TYPE 或 METHOD 的注解:

  1. 允许访问的角色
  2. 是否需要认证
  3. 是否需要授权

标注在 Controller 类才有用,若加在类上,则作用于所有方法,若标注在方法上,则以方法上的为准

意为此接口的拦截参数

java 复制代码
/**
 * Created With Intellij IDEA
 * User: 马拉圈
 * Date: 2024-08-08
 * Time: 12:50
 * <br />
 * permit: 用户必须是列表中的角色才能访问 <br />
 * authenticate: 用户需不需要通过认证 <br />
 * authorize: 用户需不需要通过授权 <br />
 * 注意: <br />
 * permit 若为 {},则代表谁都不能访问,除非 authorize 为 false <br />
 * 1. 不需要认证、不需要授权 ✅ <br />
 * 2. 需要认证、需要授权 ✅ <br />
 * 3. 需要认证、不需要授权 ✅ <br />
 * 4. 不需要认证、需要授权 ❌(必然失败) <br />
 */
@Documented
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Intercept {

    UserType[] permit() default {UserType.NORMAL_USER, UserType.MANAGER};

    boolean authenticate() default true; // 默认需要认证

    boolean authorize() default true; // 默认需要授权

}
java 复制代码
@Slf4j
public class InterceptHelper {

    public static Intercept getIntercept(Class<?> clazz) {
        // 类上的 Intercept 为初步结果
        return clazz.isAnnotationPresent(Intercept.class) ? clazz.getAnnotation(Intercept.class) : null;
    }

    public static Intercept getIntercept(Method targetMethod) {
        // 获取目标方法所在的类
        Class<?> declaringClass = targetMethod.getDeclaringClass();
        // 类上的 Intercept 为初步结果
        Intercept intercept = getIntercept(declaringClass);
        // 方法上的 Intercept 为最终结果
        return targetMethod.isAnnotationPresent(Intercept.class) ? targetMethod.getAnnotation(Intercept.class) : intercept;
    }

}

四、责任链模式

责任链:

  1. 抽象处理者
  2. 具体处理者
  3. 客户端(我习惯是责任链的链头)

设计出以下架构:

  1. 前置初始化链
    1. 初始化日志变量、设置请求 id、请求 uri、请求方法,便于全链路追踪
    2. 根据配置文件对特定接口设置的拦截参数,判断当前请求的接口是否被设置了特殊的拦截参数
    3. 请求的接口如果存在目标方法,则判断其方法上或者类上是否存在 @Intercept 注解,若存在则初始化拦截参数

若不存在拦截参数,则代表该资源没有被开发者专门进行拦截的管理,直接返回错误:api 访问失败

  1. 前置认证链
    1. 是否忽略,若 authenticate 参数为 false,则直接忽略
    2. 若认证未成功且未获取 jwt,则尝试从 header 里获取 jwt
    3. 若认证未成功且未获取 jwt,则此时从 queryString 里获取 jwt
    4. 若认证未成功,则解析 jwt,若成功解析出用户信息,则存储到本地线程变量里(若令牌即将过期,则返回一个新的 jwt)

若未认证成功,则返回错误:认证失败

  1. 前置授权链
    1. 是否武略
    2. 是否强制拦截
    3. 若未授权成功,则获取当前用户的角色,判断是否存在于拦截参数的允许访问的角色列表,若存在则授权成功

若未授权成功,则返回错误:授权失败

  1. 后置链
    1. 清除日志变量、本地线程变量

在我们的架构中而一个责任链节点应该包含:

  1. 拦截的路由
  2. 执行的前置条件
  3. 执行的代码

具体代码参考:OKR-System4.0/src/main/java/cn/bitterfree/api/interceptor at main · CarefreeState/OKR-System4.0

相关推荐
博哥爱学习10 分钟前
《Java高级编程:从原理到实战 - 进阶知识篇四》
java·开发语言
DeyouKong10 分钟前
Go反射-通过反射调用结构体的方法(带入参)
开发语言·ios·golang
jiunian_cn1 小时前
【c++】模板详解
开发语言·c++·visual studio
-曾牛1 小时前
Java面试:Spring及Spring Cloud技术深度剖析
java·spring·spring cloud·面试·springboot·javaee·面经
工藤新一¹2 小时前
C++/SDL 进阶游戏开发 —— 双人塔防(代号:村庄保卫战 19)
开发语言·c++·游戏引擎·游戏开发·sdl
啊喜拔牙2 小时前
如何在idea中写spark程序
java·spark·intellij-idea
小冯的编程学习之路2 小时前
【C++】:C++17新特性
c语言·开发语言·c++·算法
橘猫云计算机设计2 小时前
springboot基于推荐算法的景点推荐系统(源码+lw+部署文档+讲解),源码可白嫖!
java·spring boot·后端·毕业设计·推荐算法
维基框架3 小时前
Spring Boot Jpa封装快速构建Specification、OrderBy、Pageable的查询条件
java·spring boot
caig0003 小时前
JavaScript性能优化实战
开发语言·javascript·性能优化