【框架】参考 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

相关推荐
小画家~几秒前
第十八:GC 垃圾回收
java·开发语言·jvm·golang
淳于韻珊1 小时前
Java语言的散点图
开发语言·后端·golang
python_chai1 小时前
Python核心数据结构详解:元组、集合与字典
java·数据结构·python
老华带你飞2 小时前
医药垃圾分类管理系统|基于SSM+vue医药垃圾分类管理系统的系统设计与实现(源码+数据库+文档)
java·数据库·vue·毕业设计·论文·ssm·医药垃圾分类管理系统
程序员小续2 小时前
React 多个 HOC 嵌套太深,会带来哪些隐患?
java·前端·javascript·vue.js·python·react.js·webpack
mmmayang2 小时前
Golang 项目平滑重启
开发语言·后端·golang
褚翾澜3 小时前
Go语言的可选链
开发语言·后端·golang
rider1893 小时前
【9】搭建k8s集群系列(二进制部署)之安装work-node节点组件(kube-proxy)和网络组件calico
java·容器·kubernetes
ゞ 正在缓冲99%…3 小时前
leetcode274.H指数
java·算法·leetcode
程序员小杰@3 小时前
AI前端组件库Ant DesIgn X
开发语言·前端·人工智能