微服务内部服务调用@Inner

2023-11-05

1. 外部从Gateway访问,需要鉴权(eg.CURD操作)。这种是最常使⽤的,⽤户登录后正常访问接⼝,不需要我们做什么处理(可能有的接⼝需要加权限字段)。

2. 外部从Gateway访问,不需要鉴权(eg.短信验证码)。需要我们将uri加⼊到security.oauth2.client.ignore-urls配置中,可以不需要鉴权访问

3. 内部服务间⽤Feign访问,不需要鉴权(eg.Auth查询⽤户信息)。也是需要我们将uri加⼊到security.oauth2.client.ignore-urls配置中,那与第⼆种的区别就是这种情况下⼤多数都是服务可以请求另⼀个服务的所有数据,不受约束,那我们如果仅仅只配置ignore-url的话,外部所有⼈都可以通过url请求到我们内部的链接,安全达不到保障。

鉴于上述第三种情况,配置了ignore-url和Feign,此时该接⼝不需要鉴权,服务内部通过Feign访问,服务外部通过url也可以访问,所以Pigx中,加⼊了⼀种@RequestHeader(SecurityConstants.FROM)的处理⽅式。即在接⼝⽅法中,对头部进⾏判断,只有请求带上相应的Header参数时,才允许通过访问,否则抛出异常。那这时候其实我们在外⽹通过Gateway访问的时候,也可以⼿动带上这个Header参数,来达到这个⽬的。所以我们便在Gateway中设置了⼀个GlobalFilter过滤器:

这个过滤器在处理HttpRequest的时候,会删除从外部请求头⾥的SecurityConstants.FROM这个参数。此时的效果就是,这个URL从外部访问不需要鉴权,但由于Gateway的过滤,最终到达我们接⼝⽅法时,由于缺少头部信息,被拒绝访问;⽽服务间通过Feign访问,不经过Gateway,则可以正常访问。

那原始的处理⽅法和处理逻辑就是这样:⾸先将uri加⼊ingore-url,然后在接⼝的⽅法和Feign的接⼝参数中写上RequestHeader参数,最后在Feign-Client中带上这个SecurityConstants.FROM参数。既然这种逻辑都是相同的,那后⾯的pigx版本发⾏后,就使⽤AOP将此步骤抽离出来,成为了Inner。

Inner的处理流程

统⼀的ignore-url处理

⾸先我们来看看这个注解的代码

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Inner {

    /**
     * 是否AOP统一处理
     *
     * @return false, true
     */
    boolean value() default true;

    /**
     * 需要特殊判空的字段(预留)
     *
     * @return {}
     */
    String[] field() default {};
}

⾸先,在我们项⽬加载阶段,我们获取有Inner注解的类和⽅法,然后获取我们配置的uri,经过正则替换后⾯的可变参数为*,然后将此uri加⼊到ignore-url中。此时我们就能达到所有Inner配置的⽅法/类上的接⼝地址,都统⼀在项⽬加载阶段⾃动帮我们加到ignore-url中,不需要我们⼿动配置,免去了很多开发⼯作,同时也能避免我们忘记配置,⽽浪费开发时间。核⼼代码如下:

@Slf4j
@Configuration
@ConditionalOnExpression("!'${security.oauth2.client.ignore-urls}'.isEmpty()")
@ConfigurationProperties(prefix = "security.oauth2.client")
public class PermitAllUrlProperties implements InitializingBean {
    private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");
    @Autowired
    private WebApplicationContext applicationContext;

    @Getter
    @Setter
    private List<String> ignoreUrls = new ArrayList<>();

    @Override
    public void afterPropertiesSet() {
        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();

        map.keySet().forEach(info -> {
            HandlerMethod handlerMethod = map.get(info);

            // 获取方法上边的注解 替代path variable 为 *
            Inner method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Inner.class);
            Optional.ofNullable(method)
                    .ifPresent(inner -> info.getPatternsCondition().getPatterns()
                            .forEach(url -> ignoreUrls.add(ReUtil.replaceAll(url, PATTERN, StringPool.ASTERISK))));

            // 获取类上边的注解, 替代path variable 为 *
            Inner controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Inner.class);
            Optional.ofNullable(controller)
                    .ifPresent(inner -> info.getPatternsCondition().getPatterns()
                            .forEach(url -> ignoreUrls.add(ReUtil.replaceAll(url, PATTERN, StringPool.ASTERISK))));
        });

    }
}

统一的安全处理

那上边讲到的,如果我们不希望这个url可以直接被外部调用,仅能在feign功能中使用,该怎么处理?

我们使⽤⼀个Spring-AOP,在对所有Inner注解的⽅法做⼀个环绕增强的切点,进⾏统⼀的处理。在上⾯我们提到的Inner的value参数,当该参数为true时,我们对⽅法的⼊参进⾏判断,仅当符合我们定制的⼊参规则时(Pigx这⾥是⽤的@RequestHeader(SecurityConstants.FROM) 与SecurityConstants.FROM_IN做⽐较),我们对它进⾏放⾏,不符合时,抛出异常;当value为false时,咱不做任何处理,此时Inner仅起到了⼀个ignore-url的作⽤

通过这两步呢,我们⾸先是在加载时通过找到Inner注解,将相应的uri加⼊到ignore-url中,达到⾃动化配置的⽬的;之后我们⼜使⽤切⾯对Inner的⽅法进⾏环绕处理,达到安全控制。对⽐之前的处理⽅式,现在我们使⽤⼀个@Inner注解,就能很快的满⾜上⾯说的两种场景,⼤⼤节省了我们的开发时间。

合理的使⽤@Inner注解

上⾯提到的两种应⽤场景,在我们的代码中,其实都是可以使⽤Inner注解的,下⾯结合Feign做⼀个简单的⽰例,⽰例场景就是我们的获取操作日志然后保存数据:

1. 在接⼝上使⽤@Inner注解,使得url⽆需鉴权

2. 编写Feign接⼝

3.Feign-Client中调⽤接⼝,带上SecurityConstants.FROM_IN参数为内部识别

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

微服务内部服务调用@Inner 的相关文章

随机推荐

  • centos7或8安装google-authenticator身份令牌

    1 系统基础环境 说明 使用云服务器安装与本地系统两种方式安装google authenticator 基于云服务器centos7 root linux tes lsb release a LSB Version core 4 1 amd6
  • 什么是HTML语义化标签?常见HTML语义化标签大全,以及不同标签比较

    一 什么是HTML语义化标签 语义化的标签 旨在让标签有自己的含义 p 一行文字 p span 一行文字 span 如上代码 p 标签与 span 标签都区别之一就是 p 标签的含义是 段落 而 span 标签责没有独特的含义 二 语义化标
  • SQL:基础概念 + 在线数据库

    文章目录 1 基础 2 数据库基础概念整理 2 1 ER图 2 2 数据库管理工具 2 3 在线数据库 1 基础 推荐阅读 https www w3school com cn sql sql orderby asp https www ru
  • 优化器算法总结(BGD、SGD、MBGD、Momentum、NAG、Adagrad 未总结完)

    参考的两篇博文 1 优化算法总结 深度学习 https blog csdn net fengzhongluoleidehua article details 81104051 2 深度学习 优化器算法Optimizer详解 BGD SGD
  • Spring-动态代理深入了解

    前言 本篇的Spring AOP系类文章第二篇扩展了Spring 动态代理然后开发了简易的AOP类 个人主页 尘觉主页 个人简介 大家好 我是尘觉 希望我的文章可以帮助到大家 您的满意是我的动力 在csdn获奖荣誉 csdn城市之星2名 J
  • JVM内存溢出和内存泄漏的区别

    1 概念的区分 1 1 内存泄露 memory leak 程序运行结束后 没有释放 所占用的内存空间 一次内存泄漏 似乎不会有大的影响 但内存泄漏 不断累积 最终可用内存会变得越来越少 比如说 总内存大小是100 MB 有40MB的内存一直
  • 一个无源晶振和外围电路(如图)组成的振荡电路,就能发挥类似有源晶振的功能吗?

    一个无源晶振和外围电路 如图 组成的振荡电路 就能发挥类似有源晶振的功能吗 2012 06 21 22 01 曾佳乐曾佳乐曾 分类 工程技术科学 浏览1232次 从output端输出的电压只有正半周还是正半周 负半周都有 这个电路通电后 能
  • numpy平均值插补步骤及详细说明

    numpy平均值插补步骤及详细说明 1 导入numpy工具并读取数据 2 定义平均值插补函数 3 调用平均值插补函数 4 插补结果 利用 numpy对数据进行插补是一个非常常见的方法 代码也很多 但是网上的代码一般没有很详细的解释 不利于初
  • 虚拟IP原理

    高可用性HA High Availability 指的是通过尽量缩短因日常维护操作 计划 和突发的系统崩溃 非计划 所导致的停机时间 以提高系统和应用的可用性 HA系统是目前企业防止核心计算机系统因故障停机的最有效手段 实现HA的方式 一般
  • java x86 x64_jdk x86与jdk x64 有什么区别

    展开全部 1 jdk x86与jdk x64版本不同 jdk x86 32位版e68a843231313335323631343130323136353331333431366239 jdk x64 64位版 2 jdk x86与jdk x
  • c++ enable_shared_from_this

    std enable shared from this 是一个类模板 那它是用来干嘛的呢 光看它的名字可能可以猜出它是 返回指向当前对象的shared ptr智能指针 在说明它的作用前我们可以看一下如下代码 include
  • ceph分布式文件存储性能调优

    ceph分布式文件存储性能调优 一 硬件调优 二 BIOS配置 三 网络配置 四 OS配置 五 硬盘调度算法 六 软件层面 七 ceph参数调优 一 硬件调优 1 NVMe SSD 调优 目的 为减少数据跨片开销 方法 将NVMe SSD与
  • 彩笔的第一个模型:DOTA数据集YOLOv5目标检测

    目录 前言 一 下载数据集DOTA和源码 下载YOLOv5模型 切割图片并转化label为YOLO格式 2 DOTA数据集的label格式不能在YOLO模型 里直接使用 需要转化 3 需要做成coco数据集的文件结构 包括文件夹名称 二 修
  • 技术科普丨信噪比

    概念简介 信噪比 英文名称叫做SNR或S N SIGNAL NOISE RATIO 又称为讯噪比 是指一个电子设备或者电子系统中信号与噪声的比例 信噪比的计量单位是dB 对于一张图像来说 计算信噪比可以按照 20lg 信号 噪声 这个公式来
  • Andriod getContext和getActivity

    原创文章 如有转载 请注明出处 http blog csdn net myth13141314 article details 62045162 MainActivity this 表示MainActivity对象 一般用在内部类中指示外面
  • STM32+FATFS文件系统连续在同一个txt文件里写入内容

    移植好fatfs文件系统之后 我们经常要在一个txt文件下写入数据 但是这些数据可能需要多次写入 那怎么办呢 通过这几天的学习 有以下函数可以帮助我们进行多次写入数据 1 打开文件 f open filescr2 0 201711022 t
  • CAN资料整理(三):CAN的位时间、同步、位定时

    目录 一 位时间 二 同步 1 硬同步 2 重新同步 三 位定时 1 传播段延迟时间的确定 2 位定时参数确定 由于CAN属于异步通讯 没有时钟信号线 连接在同一个总线网络中的各个节点会像串口异步通讯那样 节点间会使用约定好的波特率进行通讯
  • ROS+UR机械臂系列-1- 虚拟机及ROS安装

    ROS UR机械臂系列 1 虚拟机及ROS安装 小白 刚开始使用ROS系统 希望可以成一个系列 方便大家参考 避过大坑 最开始使用的是Ubuntu20 04 ROS noetic 遇到问题时 发现很多都在用Ubuntu18 04 ROS m
  • 解决pip安装包时出现 WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None))

    错误描述 anaconda使用pip安装包时会出现无法下载的问题 或者pip直接无反应 可能会出现如下错误提示 WARNING Retrying Retry total 4 connect None read None redirect N
  • 微服务内部服务调用@Inner

    1 外部从Gateway访问 需要鉴权 eg CURD操作 这种是最常使 的 户登录后正常访问接 不需要我们做什么处理 可能有的接 需要加权限字段 2 外部从Gateway访问 不需要鉴权 eg 短信验证码 需要我们将uri加 到secur