RPC框架设计的安全性考量

news2024/10/2 10:30:17

RPC里面该如何提升单机资源的利用率,你要记住的关键点就一个,那就是“异步化”。调用方利用异步化机制实现并行调用多个服务,以缩短整个调用时间;而服务提供方则可以利用异步化把业务逻辑放到自定义线程池里面去执行,以提升单机的OPS。

1 为何要考虑安全问题?

RPC是解决应用间互相通信的框架,而应用之间的远程调用过程一般不会暴露在公网,RPC一般用于内部应用通信。

“内部”指应用都部署在同一大局域网。相对公网环境,局域网隔离性更好,相对安全,所以在RPC里很少考虑数据包篡改、请求伪造等。

那RPC里应关心什么安全问题?

2 完整的RPC应用流程

先由Provider定义好一个接口,并把这个接口的Jar包发布到私服,然后在项目中实现这接口,最后通过RPC API把这接口和其对应实现类完成对外暴露,若是Spring应用,直接定义成一个Bean即可。至此,服务提供方就完成了一个接口的对外发布。

对服务调用方就更简单,只要拿到刚才上传到私服的Jar坐标,就可把发布到私服的Jar引入项目,借助RPC动态代理功能,服务调用方直接就可在项目完成RPC调用。

安全隐患

因为私服上所有Jar坐标所有人都可看到,只要拿到Jar坐标,就可将发布到私服的Jar引入项目,完成RPC调用了吗?公司内部这种不向服务提供方咨询就直接调用的行为很少发生,一般真实业务的接口出入参数都不太简单,这样不经过咨询只靠调用方自己猜测完成调用的工作效率实在太低。

虽然这种靠猜测调用的概率很小,但当调用方在其它新业务场景要用之前项目中使用过的接口,很可能真的不跟服务提供方打招呼就直接调用。这行为对Provider很危险,因为接入新调用方就意味着承担的调用量变大,有时可能新增的调用量会成为Provider的“最后一根稻草”,导致Provider无法正常提供服务,还不知道是被谁给压垮的。

可通过公司严格流程让研发达成“君子约定”,即在应用里每次要用一个接口时,须先向服务提供方报备,这确实能在很大程度避免。但就RPC本身,可提供某种功能来解决这种问题呢?毕竟对人数多的团队,口头约定不能彻底杜绝这类问题。

3 调用方之间的安全保证

根本原因就是服务提供方收到请求后,不知道这次请求是哪个调用方发起的,没法判断这次请求是属于之前打过招呼的调用方还是没有打过招呼的调用方,所以也就没法选择拒绝这次请求还是继续执行。

只需给每个调用方设定一个唯一身份,每个调用方在调用前都先来服务提供方这登记身份,只有登记过的调用方才能继续放行,没有登记过的调用方一律拒绝。

好比坐火车凭身份证购买火车票,买票成功就类似服务调用方去服务提供方进行登记。当你进站准备上火车,须同时出示你的身份证和火车票,这两个就是代表你能上这趟火车的“唯一身份”,只有验证身份,负责检票的工作人员才会让你上车,否则拒乘。

4 RPC里的实现

先要有个可供caller进行调用接口登记的地方,“授权平台”,caller可在授权平台上申请自己应用里要调用的接口,而provider在授权平台进行审批,只有服务提供方审批后调用方才能调用。但这解决调用数据收集的问题,并没有完成真正授权认证功能,缺少一个检票环节。

搭建了授权平台,而且接口的授权数据也在这平台,可将检票环节放到授权平台。caller每次发起业务请求时,先去发一条认证请求到授权平台:“hello,我能调用这个接口吗?”

只有授权平台返回:“sure”,才继续把业务请求发到provider。

4.1 集中式认证流程

@startuml
title:集中式认证流程

participant 调用方 as 调用方
participant 授权平台 as 授权平台
participant 提供方 as 提供方

调用方 -> 授权平台++ : 我们调用 x 接口吗?
授权平台 --> 调用方-- : sure!

调用方 -> 提供方++ : 真实业务请求
提供方 --> 调用方-- : 返回结果

@enduml

这种设计没问题,整个认证过程对RPC使用者透明。问题是这授权平台承担公司内所有RPC请求的次数总和,当公司内部RPC使用程度高了,这授权平台就会成为性能瓶颈,须保证高可用。

如何优化呢?是否不需要把这认证逻辑放到业务请求过程,而是挪到初始化过程?确实可很大程度减少授权平台压力,但本质无变化,还是集中式授权平台。

5 更优方案

caller能否调相关接口,由provider说了算,就可将检票过程放到provider。在caller启动初始化接口时,带上授权平台上颁发的身份去provider认证下,当认证通过后,就认为这接口可调。

provider验票时,对照的数据来自哪儿,不能又去请求授权平台吧?

不可逆加密算法

如HMAC。provider应用里放个用于HMAC签名的私钥,在授权平台上用这私钥为申请调用的调用方应用进行签名,这签名生成的串就变成caller唯一身份。

provider收到caller的授权请求后,只需验证这个签名跟调用方应用信息是否对应得上,这样集中式授权瓶颈就不存在了。

HMAC来做认证,服务提供方是使用 “公钥” 验证服务调用方的签名串。事先要生成公私钥。

6 服务发现也有安全问题?

解决了调用方之间的安全认证问题。还有其它安全问题吗?

服务提供方会把接口Jar发布到私服,以方便调用方能引入项目快速完成RPC调用,可能有人拿到Jar后,发布出来一个服务提供方呢?导致调用方通过服务发现拿到的服务提供方IP地址集合里有那个伪造的提供方。

解决这个问题的根本:要把接口跟应用绑定,一个接口只允许有一个应用发布提供者,避免其它应用也能发布该接口。

实现

服务提供方启动时,把接口实例在注册中心登记。

可利用这流程,注册中心在收到服务提供方注册请求时,验证请求过来的应用是否跟接口绑定的应用一样,只有相同才允许注册,否则返回错误信息给启动的应用,避免假冒的服务提供者对外提供错误服务。

7 总结

RPC常用于解决内网应用之间的调用,内网环境相对公网也没有那么恶劣,也要去建立一套可控的安全体系,去防止一些错误行为。

对RPC,我们所关心的安全问题不会有公网应用那么复杂,我们只要保证让服务调用方能拿到真实的服务提供方IP地址集合,且服务提供方可以管控调用自己的应用就够了。

8 FAQ

前面讲的调用方之间的安全问题,我们更多只是解决认证问题,并没有解决权限问题。一个RPC接口定义里面包含多个方法,目前只是解决你能不能调用接口,并没有解决你能调用我接口里面的哪些方法,如何解决?

订单中间件,提供服务防止未知系统任意调用,服务调用管理功能,到方法级:

  • 提供服务调用的申请模板,描述那个系统,那个应用,调用我们那个服务的那个方法,调用量多少,调用应用负责人是谁,对接研发谁,还有别的配置信息
  • 把调用配置信息落库,然后放入缓存,使用调用者信息及我们提供服务的信息组成key,放入redis
  • 调用方调用我们时,去做拦截和鉴权
  • 统一部署平台中有系统和应用的唯一标识信息,这些信息在调用接口时作为入参的一部分,就能实现细粒度到方法基本的控制

另外,就是使用token,也是申请时分发,本质一样的,就看对应的配置信息存储在哪里。

服务端提供的安全校验方式

md5摘要校验

安全级别较低,服务端直接提供或者网关代劳。

非对称加密算法

签名(RSA和HMAC等算法,服务端直接提供或者网关代劳。

Oauth2授权

有单独的授权服务,四种模式。

觉得rpc好像跟k8s有点像,k8s是类似把一个大服务拆分成很多模块,完了之后来把这些微服务管理起来,而rpc是提供了一系列接口,通过网络的方式,让各个调用方去调用。

k8s可以看做rpc升级版本。

可以从鉴权和授权2个方面来看(参考k8s):

  • 鉴权可以用 token 的方式,token鉴权应该是目前用的最多的一种认证方式
  • 授权可以用 RBAC 方式,类似k8s里面的 serviceAccount 和 role 和 roleBinding 等

认证和授权一般都是同时使用。

我们之前是用的配置中心来存储对应的关系,B服务可以被那些服务调用或者不可以被那些服务调用,同时,也有B服务的接口权限,然后内部网关同步相关信息,保存到内存缓存中,当调用方请求经过网管时,获取调用方,服务方,服务方具体的接口,然后去校验相关的信息,判断是否可以放行,我们的鉴权没有放在服务方本身去实现,是在网关实现的。

前提就是怎么识别调用方的身份,比如应用id。

请问服务提供方对服务调用方的授权认证后,已认证的状态应该存在服务提供端本地吧,那服务端集群中各个节点之间怎么共享同一个服务调用方应用的认证状态呢?还是说每次调用到不同的的服务提供方节点都需要从新进行鉴权?或者说是服务调用方在获取到服务提供方的IP列表后统一进行一次遍历的授权认证?

每个节点都得鉴权一次。

RPC可以用于公网通信吗?鉴权放在服务端对服务端的压力是不是也挺大的?

公网一般比较少,鉴权只要一次开销,压力还是可控的。

这种授权方式,对于调用方而言,加密后的签名怎么维护呢,感觉有代码侵入呀?

统一授权平台上获取。

首先肯定是在服务端做,其次是应该在每一个服务提供端对其接口做权限审核,假如一个服务端提供10个接口出来,5个可以被A调用,另外5个不能被A服务调用,那么就应该有个配置文件配置这调用端和服务端各个接口的权限配置信息,这个权限配置应该放在配置中心,然后每个服务端会动态获取配置信息根据配置信息来决定是否拒绝服务。对于新增的调用服务,它需要先申请权限,然后服务端提供方修改配置文件对其提供服务。

这也是一种思路。

权限控制应放在服务提供方,权限控制规则可以放到单独管理节点,服务启动的时候从管理节点获取规则,权限规则变更后下发到服务节点。

这有一个前提就是统一调用方身份的问题,规则里面是按照什么对象来识别身份。

进行接口授权的同时也进行接口方法的授权。

授权和认证都需要考虑。

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

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

相关文章

springboot 注解

上一篇:初识springboot接收参数常用注解RequestBody 常用于POST表单提交参数接收RequestMapping("/test") public String test(RequestBody String data){return data; }PathVariable 获取路径上的参数:/test/{id} RequestMapping("/test…

开源流程引擎Camunda

开源流程引擎Camunda 文章作者:智星 1.简介 Camunda是一个轻量级的商业流程开源平台,是一种基于Java的框架,持久层采用Mybatis,可以内嵌集成到Java应用、SpringBooot应用中,也可以独立运行,其支持BPMN&a…

ThingsBoard-规则引擎介绍

1、什么是规则引擎? 规则引擎是一个易于使用的框架,用于构建基于事件的工作流。有3个主要组成部分: 消息- 任何传入事件。它可以是来自设备的传入数据、设备生命周期事件、REST API 事件、RPC 请求等。规则节点- 对传入消息执行的功能。有许多不同的节点类型可以过滤、转换…

微信 API 中调用客服消息接口提示错误返回限制

错误的信息如下:errcode45015, errmsgresponse out of time limit or subscription is canceled rid: 5f8fd8b7-0f8aa1a9-4b6215a5微信的文档看着这微信不清不楚的文档:微信公众平台在这个文档界面中,有句话:这句话,我…

【信息学CSP-J近16年历年真题64题】真题练习与解析 第13题之标题统计

标题统计 描述 凯凯刚写了一篇美妙的作文,请问这篇作文的标题中有多少个字符? 注意:标题中可能包含大、小写英文字母、数字字符、空格和换行符。统计标题字符数时,空格和换行符不计算在内。 输入 输入文件只有一行,一个字符串 s。 输出 输出文件只有一行,包含一个整…

原型、原型链、__proto__与prototype的区别、继承

一.什么是原型与原型链 根据MDN官方解释: JavaScript 常被描述为一种基于原型的语言——每个对象拥有一个原型对象[[Prototype]] ,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类…

Kafka第二章:生产者案例

系列文章目录 Kafka第一章:环境搭建 Kafka第二章:生产者案例 文章目录系列文章目录前言一、创建项目1.创建包2.添加依赖二、编写代码1.普通异步发送2.同步发送三.生产者发送消息的分区策略1.指定分区2.自定义分区总结前言 上次完成了Kafka的环境搭建&a…

RabbitMQ-Exchanges交换机

一、介绍 RabbitMQ消息传递模型的核心思想是:生产者生产的消息从不会直接发送到队列。实际上,通常生产者甚至不知道这些消息传递到了哪些队列中。相反,生产者只能将消息发送到交换机,交换机工作的内容非常简单,一方…

七、Java框架之MyBatisPlus

黑马课程 文章目录1. MyBatisPlus入门1.1 MyBatisPlus入门案例步骤1:创建spring boot工程步骤2:配置application.yml步骤3:创建数据库表(重点)步骤4:编写dao层步骤5:测试1.2 标准数据层开发标准…

CSDN每日一练:一维数组的最大子数组和

题目名称&#xff1a;一维数组的最大子数组和 时间限制&#xff1a;1000ms内存限制&#xff1a;256M 题目描述 下面是一个一维数组的 “最大子数组的和” 的动态规划的解法 # include <iostream> # include <stdio.h> # include <string.h>int MaxSum(int* a…

多传感器融合定位十五-多传感器时空标定(综述)

多传感器融合定位十五-多传感器时空标定1. 多传感器标定简介1.1 标定内容及方法1.2 讲解思路2. 内参标定2.1 雷达内参标定2.2 IMU内参标定2.3 编码器内参标定2.4 相机内参标定3. 外参标定3.1 雷达和相机外参标定3.2 多雷达外参标定3.3 手眼标定3.4 融合中标定3.5 总结4. 时间标…

基于live555源码的rtsp服务器

下载live555源码 http://www.live555.com/liveMedia/public/ 在Linux系统的自定义目录下输入&#xff0c;下载源码&#xff1a; wget http://www.live555.com/liveMedia/public/live.2023.01.19.tar.gz解压源码&#xff1a; tar -xvf live.2023.01.19.tar.gz当前目录下运行&…

前端卷算法系列(一)

前端卷算法系列&#xff08;一&#xff09; 两数之和 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同…

无重复字符的最长子串-力扣3-java

一、题目描述给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。示例 1:输入: s "abcabcbb"输出: 3 解释: 因为无重复字符的最长子串是 "abc"&#xff0c;所以其长度为 3。示例 2:输入: s "bbbbb"输出: 1解释: 因为…

Springboot Web开发

文章目录一. 静态资源访问1. 配置静态资源访问前缀2. 修改默认静态资源存放目录3. Webjars4. 欢迎页支持5. 自定义Favicon二. 请求处理1. 路径变量2. 请求头处理3. 查询字符串处理4. 获取Cookie的值5. 获取请求体的值6. 获取请求域中的数据7. 矩阵变量一. 静态资源访问 只要静…

ChatGPT全球爆火,究竟有何特别之处?

​ 新年复工不过半月&#xff0c;职场人似乎就受到了来自AI的“威胁”&#xff0c;关于人工智能聊天系统ChatGPT的热搜频频上榜。 ChatGPT不仅拟人&#xff0c;更类人&#xff0c;甚至被认为是职场人的“敌人”。 那么&#xff0c;ChatGPT能替代哪些职业&#xff1f; 它自己的回…

STP协议基础

STP协议技术来源二层环路及危害二层交换机网络的冗余性与环路人为错误导致的二层环路二层环路带来的问题STP生成树协议STP概述STP基本概念桥ID根桥COSTRPC&#xff08;Root Path Cost&#xff09;根路径开销PORT ID端口IDBPDU桥协议数据单元STP的计算过程&#xff08;1&#xf…

VS中安装gismo库

文章目录前言一、下载安装paraview直接下载压缩包安装就可以了解压后按步骤安装即可二、gismo库的安装gismo库网址第一种方法&#xff1a;第二种方法第三种方法&#xff1a;用Cmake软件直接安装首先下载cmake软件[网址](https://cmake.org/download/)安装gismo库三、gismo库的使…

ChatGPT闭包解答

怎么理解javaScript闭包 JavaScript 闭包是一种特殊的对象&#xff0c;它包含了函数及其相关作用域中的变量。它允许函数访问并保存其外部作用域中的变量&#xff0c;即使该函数已经离开了其作用域。 闭包的一个常见应用场景是封装私有变量。例如&#xff0c;在一个对象的方法内…

Android IO 框架 Okio 的实现原理,如何检测超时?

本文已收录到 AndroidFamily&#xff0c;技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 提问。 前言 大家好&#xff0c;我是小彭。 在上一篇文章里&#xff0c;我们聊到了 Square 开源的 I/O 框架 Okio 的三个优势&#xff1a;精简且全面的 API、基于共享的缓冲区设计以…