Sa-Token的v1.39.0自定义鉴权注解怎么玩

news2024/9/20 20:49:21

个人博客:无奈何杨(wnhyang)

个人语雀:wnhyang

共享语雀:在线知识共享

Github:wnhyang - Overview


image

简介

Sa-Token最新的v1.39.0版本的更新日志中有这么一句话

核心:

  • 升级:重构注解鉴权底层,支持自定义鉴权注解了。 [重要]

正巧最近有看一个关于鉴权的东西,顺便看一下吧!

常见的自定义注解鉴权

目标:对于后端开放的api进行鉴权。

1、自定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ApiAccess {

    /**
     * 交易码
     *
     * @return 交易码
     */
    String transCode();
}

2、定义拦截器

@Slf4j
@Component
public class ApiAccessInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("ApiAccessInterceptor preHandle");
        if (handler instanceof HandlerMethod) {
            Method method = ((HandlerMethod) handler).getMethod();
            if (method.isAnnotationPresent(ApiAccess.class)) {
                ApiAccess apiAccess = method.getAnnotation(ApiAccess.class);
                String transCode = apiAccess.transCode();
                String transCodeHeader = request.getHeader("transCode");
                String token = request.getHeader("token");
                if (!StringUtils.hasText(transCodeHeader) || !StringUtils.hasText(token)) {
                    throw new RuntimeException("transCode or token is empty");
                }
                log.info("transCode: {}, transCodeHeader:{}, token:{}", transCode, transCodeHeader, token);
                if (!transCode.equals(transCodeHeader)) {
                    throw new RuntimeException("transCode not match");
                }

                ApiAccessUtil.valid(transCode, token);
            }
        }
        return true;
    }
}

下面是辅助验证的方法,真实生产上应该是查数据库或其他。

public class ApiAccessUtil {

    public static final List<ApiAccessPO> API_ACCESS_LIST = new ArrayList<>();

    static {
        API_ACCESS_LIST.add(new ApiAccessPO("wnhyang01", "123456"));
        API_ACCESS_LIST.add(new ApiAccessPO("wnhyang02", "234567"));
        API_ACCESS_LIST.add(new ApiAccessPO("wnhyang03", "888888"));
        API_ACCESS_LIST.add(new ApiAccessPO("wnhyang04", "666666"));
    }

    public static void valid(String transCode, String token) {
        for (ApiAccessPO apiAccessPO : API_ACCESS_LIST) {
            if (apiAccessPO.getTransCode().equals(transCode) && apiAccessPO.getToken().equals(token)) {
                return;
            }
        }
        throw new RuntimeException("invalid access");
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    private static class ApiAccessPO {

        private String transCode;

        private String token;
    }
}

3、配置拦截器

@Slf4j
@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {

    private final ApiAccessInterceptor apiAccessInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(apiAccessInterceptor);
    }
}

4、验证

@Slf4j
@RestController
@RequestMapping("/api")
public class ApiAccessController {

    @GetMapping("/wnhyang01")
    @ApiAccess(transCode = "wnhyang01")
    public String wnhyang01() {
        return "wnhyang01";
    }

    @GetMapping("/wnhyang02")
    @ApiAccess(transCode = "wnhyang02")
    public String wnhyang02() {
        return "wnhyang02";
    }

    @GetMapping("/wnhyang03")
    @ApiAccess(transCode = "wnhyang03")
    public String wnhyang03() {
        return "wnhyang03";
    }

    @GetMapping("/wnhyang04")
    @ApiAccess(transCode = "wnhyang04")
    public String wnhyang04() {
        return "wnhyang04";
    }
}

测试可知,只有HeadertransCodetoken都不为空,并且HeadertransCode与接口配置的唯一transCode一致前提下,transCodetoken都能通过验证才能通过拦截器。

image

使用新版Sa-Token完成

自定义注解

1、自定义注解

与前面一致就行

2、创建注解处理器

实现SaAnnotationHandlerInterface接口的两个抽象方法就好,checkMethod放鉴权逻辑,与前面的拦截器方法一致就好,将拦截器里使用的request替换为SaHolder.getRequest()(关于这个自己可以看官网文档或者源码都可,我之前介绍Sa-Token组件时也有提过)。

注意使用@Component将类注册为IOCBean就省去了手动注册了。

SaAnnotationStrategy.instance.registerAnnotationHandler(new CheckAccountHandler());
@Slf4j
@Component
public class ApiAccessHandler implements SaAnnotationHandlerInterface<ApiAccess> {

    @Override
    public Class<ApiAccess> getHandlerAnnotationClass() {
        return ApiAccess.class;
    }

    @Override
    public void checkMethod(ApiAccess apiAccess, Method method) {
        log.info("checkMethod");
        String transCode = apiAccess.transCode();
        String transCodeHeader = SaHolder.getRequest().getHeader("transCode");
        String token = SaHolder.getRequest().getHeader("token");
        if (!StringUtils.hasText(transCodeHeader) || !StringUtils.hasText(token)) {
            throw new RuntimeException("transCode or token is empty");
        }
        log.info("transCode: {}, transCodeHeader:{}, token:{}", transCode, transCodeHeader, token);
        if (!transCode.equals(transCodeHeader)) {
            throw new RuntimeException("transCode not match");
        }

        ApiAccessUtil.valid(transCode, token);
    }
}

3、配置拦截器

与前面一样,删除自己的拦截器配置,加上SaInterceptor就好

@Slf4j
@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {

    private final ApiAccessInterceptor apiAccessInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 删除 registry.addInterceptor(apiAccessInterceptor);
        registry.addInterceptor(new SaInterceptor());
    }
}

4、验证

试过你就话发现,前后效果一样。

怎么做到的?

对比差异

通过Idea选择不同版本的提交记录对比,因为我使用的是Jdk17+boot3所以看的是图下的差异,其他类同的。

image

可以看到,SaInterceptor鉴权逻辑从左边一坨变为了右边一行。

image

sa-token-core的对比来看,原来的SaStrategy删除了所有相关于鉴权的方法,与此对应新增了SaAnnotationStrategy类。

image

SaAnnotationStrategy默认注册了原来的所有鉴权处理器。

image

SaInterceptor鉴权使用的就是SaAnnotationStrategycheckMethodAnnotation方法,其就是将所有注册的注解处理器跑一遍。

/**
 * 对一个 [Method] 对象进行注解校验 (注解鉴权内部实现)
 */
@SuppressWarnings("unchecked")
public SaCheckMethodAnnotationFunction checkMethodAnnotation = (method) -> {
    // 遍历所有的注解处理器,检查此 method 是否具有这些指定的注解
    for (Map.Entry<Class<?>, SaAnnotationHandlerInterface<?>> entry: annotationHandlerMap.entrySet()) {

        // 先校验 Method 所属 Class 上的注解
        Annotation classTakeAnnotation = instance.getAnnotation.apply(method.getDeclaringClass(), (Class<Annotation>)entry.getKey());
        if(classTakeAnnotation != null) {
            entry.getValue().check(classTakeAnnotation, method);
        }

        // 再校验 Method 上的注解
        Annotation methodTakeAnnotation = instance.getAnnotation.apply(method, (Class<Annotation>)entry.getKey());
        if(methodTakeAnnotation != null) {
            entry.getValue().check(methodTakeAnnotation, method);
        }
    }
};

默认的所有注解处理器可以看sa-token-corecn.dev33.satoken.annotation.handler包。

可以知道其实就是将原来的SaStrategy的鉴权方法抽象到SaAnnotationHandlerInterface,并提供鉴权策略类和注解处理器集合。

image

另外记得前面说的如果自定义实现了SaAnnotationHandlerInterface并且加入了Spring Ioc容器,就不用手动注册了吗?其实这个并不必多说,想想就知道是怎么实现的。

还是废话一下吧。

core里的默认注解处理器并不需要加入Spring Ioc,因为默认的初始化方法已经讲这些注册了,而用户如果自己扩展了注解处理器,就会被autoconfigSaBeaInject找到并完成注册。
在这里插入图片描述

小结

作为源码的主导者其实应该更加清楚,项目的不足,主导项目未来的规划发展,不仅仅是对于使用者提出的issues,更加应该是项目开发者的初心。

最后一句话:停在港口的船最安全,但这不是造船的意义!

写在最后

拙作艰辛,字句心血,望诸君垂青,多予支持,不胜感激。


个人博客:无奈何杨(wnhyang)

个人语雀:wnhyang

共享语雀:在线知识共享

Github:wnhyang - Overview

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2142210.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

剖解杨辉三角

杨辉三角 思路&#xff1a; 我们将上述转换为一个二维数组&#xff0c;即可实现效果 另外在实现代码之前我们要了解Java中是如何实现二维数组的&#xff1a; 实现代码如下&#xff1a; public List<List<Integer>> generate(int numRows){List<List<Integ…

MySQL-DQL(数据查询语言)

数据查询语言(DQL-Data Query Language) 代表关键字&#xff1a;select MySQL语句执行顺序 1、基础操作 1.1 启动服务 a.手动启动 我的电脑->右键->管理->服务->mysql->右键启动/启动 b.命令方式 在管理员模式下运行cmd,执行如下操作&#xff1a; net sta…

Nginx 跨域 + 无法设置 Cookie 解决办法

今天来分享一下关于项目部署上线时怎么解决跨域问题!!! 首先感谢一下大佬的方法,才让这个困扰我很久的问题得以解决!!! 这也是我请教大佬才解决的问题,大佬和我说,这是他耗费两周才解决的问题,我这也是属于前人栽树后人乘凉了,嘿嘿嘿!!! 前端问题 前端没有携带 cookie 导致后端…

WGCAT可以导出工单吗

可以的 WGCAT工单管理系统&#xff0c;支持将工单数据导出为PDF文件

Mac OS系统如何下载安装Python解释器

目录 Mac安装Python的教程 mac下载并安装python解释器 如何下载和安装最新的python解释器 访问python.org&#xff08;受国内网速的影响&#xff0c;访问速度会比较慢&#xff0c;不过也可以去我博客的资源下载&#xff09; 打开历史发布版本页面 进入下载页 鼠标拖到页面…

基于vue框架的宠物领养管理系统88v55(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;用户,宠物分类,宠物信息,领养信息,宠物动态,捐赠物资,领养进度,友情链接 开题报告内容 基于Vue框架的宠物领养管理系统开题报告 一、项目背景与意义 随着社会的进步和人们生活水平的提高&#xff0c;宠物已成为许多家庭不可或缺的一部…

滑动窗口(2)_无重复字符的最长字串

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 滑动窗口(2)_无重复字符的最长字串 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目…

Cortex-A7:处理器组成架构

0 参考资料 ARM Cortex™-A Series Version: 4.0 Programmer’s Guide.pdf 1 Cortex-A7处理器组成架构 1.1 Cortex-A7处理器简介 Cortex-A7处理器是ARM公司推出的用于入门级智能手机、平板电脑以及其他低功耗移动设备的处理器架构。 1.2 Cortex-A7处理器组成框图 注&#xf…

idea一个窗口打开多个仓库的代码

一、背景 最近新进了一家外包公司&#xff0c;这个项目由于是微服务的&#xff0c;且每个微服务都独立用一个仓库进行代码管理。看项目的时候&#xff0c;我们不能一个窗口&#xff0c;只打开一个仓库代码&#xff0c;那样看起来会非常麻烦&#xff0c;一开始对项目全貌的了解…

osg中显示3dtiles和cesiumIon

本文分析osgEarth中的osgEarthCesium模块&#xff0c;分析3dtiles和cesiumIon整个流程&#xff0c;并展示CesiumIon地形显示的例子。 目录 1 osgEarthCesium结构分析2 CesiumIon地形显示 内容 1 osgEarthCesium结构分析 1.1 CesiumNative3DTileslayer图层 osgEarth中采用图层…

数据结构修炼——顺序表和链表的区别与联系?

目录 一、线性表二、顺序表2.1 概念及结构2.2 接口实现2.3 一些思考以及顺序表的缺点 三、链表3.1 概念及结构3.2 链表的分类3.3 链表的实现3.3.1 无头单向非循环链表3.3.2 带头双向循环链表 四、顺序表和链表的区别 一、线性表 线性表&#xff08;linear list&#xff09;是n…

RDMA应用场景及效果

GPU Direct 参考&#xff1a;网络架构如何支持超万卡的大规模 AI 训练&#xff1f;| AICon_芯片与网络_InfoQ精选文章 GPU 网络的情况已经发生了很大变化。每个 GPU 都有自己的内部互联&#xff0c;例如 NVIDIA 的 A100 或 H800&#xff0c;它们内部的 NVLink 互联可以达到 6…

命令语境中的“可以”的字词含义分析

摘要 在语言交流中&#xff0c;词汇的使用经常受到语境的影响。本文探讨了“可以”一词在上司与下属之间的互动中所表达的命令含义。通过分析语料和实例&#xff0c;发现“可以”在某些情况下并不传达许可的含义&#xff0c;而是被用作一种隐性命令。本文讨论了这一现象的成因…

【数据结构】快速排序详解(递归版本)

目录 0. 前言 1. 快速排序的基本思想 2. 快速排序的不同版本的实现 2.1 hoare版本 2.1.1 单趟排序动图演示 2.1.2 递归展开多个子区间进行单趟排序 2.1.3 代码的具体实现 2.1.3.1 霍尔法单趟排序代码 2.3.1.2 霍尔法递归代码 2.2 挖坑法 2.2.1 单趟排序方法动图演示…

二叉树的层序遍历(c)

我们先来了解一下什么是二叉树的层序遍历&#xff01; 层序遍历的理解 下图是一棵二叉树&#xff0c; 层序遍历这棵二叉树的顺序是&#xff1a; 1→2→3→4→5→6→7&#xff0c; 看图也很简单易懂&#xff0c; 第一层→第二层→第三层。 层序遍历的实现 如果二叉树的结…

Python3将Excel数据转换为文本文件

文章目录 python3安装使用Python将Excel数据转换为文本文件&#xff1a;逐步指南openpyxl库简介前提条件脚本解析代码详细解析实际应用场景使用示例 结论 python3安装 centos安装python3 Python3基础知识 使用Python将Excel数据转换为文本文件&#xff1a;逐步指南 在数据处理…

文本多语言 AI 摘要 API 数据接口

文本多语言 AI 摘要 API 数据接口 文本 / 文本摘要 AI 生成文本摘要 AI 处理 / 智能摘要。 1. 产品功能 支持多语言摘要生成&#xff1b;支持长文本处理&#xff1b;基于 AI 模型&#xff0c;持续迭代优化&#xff1b;不存储 PDF 文件&#xff0c;处理完即释放&#xff0c;保…

公路数据集、桥梁数据集、隧道数据集、地铁数据集、水坝数据集、挡土墙数据集

数据集概览 这个大规模的数据集专注于建筑裂缝检测&#xff0c;涵盖了地上设施&#xff08;如公路桥梁、铁路桥梁、水坝、挡土墙&#xff09;和地下SOC设施&#xff08;如公路/铁路隧道、地铁、水隧道&#xff09;。数据集包含了来40个市、县、区的不同SOC设施的52万张图像&…

显卡GPU电源、ATX电源、主板电源的一些关系?如何连接显卡/GPU电源?

文章目录 背景ATX电源在ATX接出来的电源线 实测数据PC主机开关机和复位&#xff1a;3.3V显卡16-pin 12VHPWR 如何连接显卡/GPU电源综述 背景 折腾装机、装显卡&#xff0c;ATX电源&#xff0c;各种转来转去。搞得云里雾里&#xff0c;如何删繁就简。找到根源。 本文介绍ATX电源…

数学公式篇

【一元二次方程的根】 x − b b 2 − 4 a c 2 a x {\frac{-b\sqrt{b^2-4ac}}{2a}} x2a−bb2−4ac ​​ △ b 2 − 4 a c △ b^2-4ac △b2−4ac 其中根的判别式 △ > 0 &#xff0c;有两个实根 △>0&#xff0c;有两个实根 △>0&#xff0c;有两个实根 其中根…