接口鉴权功能的实现

article/2025/9/19 6:46:09

一、背景

随着系统的发展,单体应用逐渐演化成微服务架构。系统微服务化之后,若干个微服务之间会有调用。同个部门内实现的服务会被内部调用,一般风险是可控的。但是如果服务提供给别的部门使用之后,在不了解对方的使用场景,接口调用QPS等,如果对方接口调用量过大,会影响整个使用该服务的调用方,且对接口的安全性也会有风险。在这种情况下,每个微服务都需要对调用者进行鉴权。

基本的鉴权维度有:

  • 应用鉴权:对方在调用我方服务某个接口的时候,需要将对方的用户标识,如appKey,传过来。我方看此appKey是否有授权调用的权限,没有直接返回失败;有授权即可正常返回结果;
  • 接口鉴权:更细粒度的鉴权,在应用鉴权通过之后,还需要对某个接口进行鉴权。如:团队A想要调用订单服务,我们只想开发订单查询接口的权限,而涉及到订单退款等操作类的接口可拒绝对方访问。常见的接口鉴权有RPC接口之间的调用鉴权和HTTP接口调用鉴权。

二、需求分析

1、基本实现方案

首先,我们能想到的最基本的实现方案:

  • 调用方申请访问权限,服务方授权之后会生成调用方对应的密码,存储到DB/缓存等具有存储功能的组件中,appKey <—> password
  • 调用方在调用接口时,需要将appKey和password一起当做参数传过来;
  • 服务方在收到请求之后取出请求中的参数appKey和密码password,根据apppKey从DB/缓存等获取对应密码,判断服务方存储的密码与对方传过来的密码是否一致,不一致则拒绝访问。

2、重放攻击

上述流程是最简单的实现,但是存在重放攻击的风险。

重放攻击是指:

重放攻击(Replay Attacks)又称重播攻击、回放攻击,是指攻击者发送一个目的主机已接收过的包,来达到欺骗系统的目的,主要用于身份认证过程,破坏认证的正确性。重放攻击可以由发起者,也可以由拦截并重发该数据的敌方进行。攻击者利用网络监听或者其他方式盗取认证凭据,之后再把它重新发给认证服务器。重放攻击在任何网络通过程中都可能发生,是计算机世界黑客常用的攻击方式之一。

注:来源于百度百科

通俗点解释:攻击者利用网络监听或其他方式截取A发送给B的报文,并把由A加密的报文发送给B,使B误以为入侵者就是A,然后主机B向伪装成A的攻击者发送应当发送给A的报文。

3、优化方式

(1)优化方式一:数据加密

调用方将调用方身份信息和密码通过明文的方式传递过来,这个过程会被第三方截取获取到appKey和password,第三方可以根据获取到的信息伪装成已认证的调用方去调用服务方服务获取接口信息,对服务方服务的稳定性、安全性造成威胁。这就是“重放攻击”。

解决办法:

对数据进行加密。

  • 调用方将调用的接口名 + appKey + 密码 拼在一起,通过加密算法对其加密生成一个token值,然后再将token值拼接在原调用的url后发送至服务方,如:http://localhost:8080/user?getUserInfo?userId=1234&appKey=abc&token=dasadjij21oijiooodsadaodjaosnd

  • 服务方接收到调用方发送的请求后,解析获取到appKey、token值,根据appKey从服务方存储地获取到对应password值,然后用同样的加密算法生成服务端的token值:token_s,用token_s与调用方的token值进行比较,相同,则允许访问;不相同,则拒绝访问。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bfnGoFyi-1575984360956)(/Users/wanggenshen/Library/Application%20Support/typora-user-images/image-20191204113153975.png)]

(图片来源:极客时间https://time.geekbang.org/column/article/171760)

(2)优化方式二:数据加密 + 随机数

上述方式对于安全性要求不高的内部系统已经绰绰有余。但是这种设计仍然存在重放攻击的风险:由于生成的token值是固定的,攻击者可以花费一定的时间去破解。所以需要继续优化token生成算法,生成动态token来避免这种风险。

解决办法:

为了生成动态的token,引入一个随机数,在加密的时候也对随机数进行加密,这样每次生成的token就是动态变化的。一般使用时间戳作为随机数,使用时间戳作为随机数的好处是:接收方解析到时间戳后还可以验证token是否过期,比如时间戳是一年之前对应的时间戳,自然不允许访问;

  • 调用方对 url + appKey + 密码 + 时间戳 进行加密,生成一动态token,拼接在url后,同时拼接上时间戳,发送给服务方;

  • 服务方接收到请求之后,

    • 首先解析出 appKey、密码、时间戳、token;

    • 再校验时间戳是否在时间窗口内,比如1小时;校验不通过则认为token过期直接拒绝访问,通过进入下一步;

    • 然后根据appKey去查询对应的passwrod_s,使用相同的加密算法对

      url + appKey + passwrod_s + 时间戳 进行加密生成新token_s,比较

      token 和 token_s:相同,允许访问;不相同;拒绝访问;

示意图如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xV425cOz-1575984360957)(/Users/wanggenshen/Library/Application%20Support/typora-user-images/image-20191204135912522.png)]

(图片来源:极客时间https://time.geekbang.org/column/article/171760)

4、时序图

上述时序图如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jErD4PQb-1575984360959)(/Users/wanggenshen/Library/Application%20Support/typora-user-images/image-20191210212456359.png)]

三、代码实战

上述方式得到的功能点列表如下:

  • (1)把 URL、appKey、密码、时间戳拼接为一个字符串;
  • (2)对字符串通过加密算法加密生成 token;
  • (3)将 token、appKey、时间戳拼接到 URL 中,形成新的 URL;
  • (4)解析 URL,得到 token、appKey、时间戳等信息;
  • (5)从存储中取出 appKey 和对应的密码;
  • (6)根据时间戳判断 token 是否过期失效;
  • (7)验证两个 token 是否匹配;

经过分析可知,设计3个功能:

  • Url操作相关,包括Url拼接参数和解析Url;
  • Token操作相关,包括token生成、判断token过期、判断token是否匹配;
  • appKey存储和查询;

所以按领域模型划分,总共有3个模型,对应3个类,如下:

(1)Url不仅包括HTTP接口url请求,也有RPC接口请求,因此抽象封装成ApiRequest类:

(2)Token类设计:

AuthToken

(3)AppKey查询,为了抽象,提供接口:

(4)定义好领域模型的设计之后,需要将这些类组装起来并提供入口:

public interface ApiAuthencator {void auth(String url);void auth(ApiRequest apiRequest);
}

(5)测试

为了更好的测试效果,提供了InvokerController类,来模拟客户端调用时token生成、拼接url、触发服务端鉴权等动作。

完整代码见:完整代码


参考:极客时间《设计模式之美》


http://chatgpt.dhexx.cn/article/1MlBpp7T.shtml

相关文章

JWT鉴权

文章目录 一、什么是JWT二、JWT能做什么三、JWT介绍以及和传统Session的区别1)基于传统的Session认证2)基于JWT认证 四、JWT的构成和认证流程五、JWT的优缺点 一、什么是JWT JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained …

API签名鉴权设计

鉴权作用 在实际的业务中&#xff0c;必然会存在和其他平台系统进行数据传输。这个时候出于对数据的保密要求&#xff0c;都会对接口&#xff08;API&#xff09;添加鉴权机制&#xff0c;识别调用方的真实身份&#xff0c;对未通过鉴权的请求不做任何业务处理&#xff0c;以帮…

ak和sk怎么认证 海康威视_aksk鉴权

简介 鉴权功能的位置处于基础服务的接入网关中。 1. 认证简介 本鉴权方案是在api层面上进行,通过使用Access Key/Secret Key加密的方法来对验证某个请求的调用者身份。 当接入网关接收到业务调用方的请求时,将使用相同的SK和同样的认证机制生成认证字符串,并与用户请求中包含…

Kafka鉴权

1.SecurityProtocol 参见官方介绍 如图第一个是无需加密&#xff0c;无需鉴权的 第二个是使用sasl鉴权&#xff0c;不加密 该参数需要在服务端进行配置&#xff0c;client端也需要进行相应的配置 2.sasl.mechanism 消息收发的机制&#xff0c;默认为PLAIN。具体介绍参见该文档…

后端认证鉴权

之前我们把redis缓存工具模块做好了、下面结合RBAC权限模型&#xff0c;我们来进行用户的认证鉴权设计。关于RBAC权限模型在之前的文章跟网上都有很多很详细的描述&#xff0c;这里就简单说一下、就是通过用户关联角色&#xff08;多对多&#xff09;、角色关联权限&#xff08…

Postman鉴权

Ok, 今天我们来学习 一下 鉴权 鉴权&#xff08;authentication&#xff09; 是指验证用户是否拥有访问系统的权利。传统的鉴权是通过密码来验证的。这种方式的前提是&#xff0c;每个获得密码的用户都已经被授权。在建立用户时&#xff0c;就为此用户分配一个密码&#xff0c;…

详解 http 鉴权

详解 http 鉴权 【总结分享】10种常用前后端鉴权方法&#xff0c;让你不再迷惘 &#x1f31f;&#x1f31f;&#x1f31f; 前端开发登录鉴权方案完全梳理 &#x1f31f;&#x1f31f;&#x1f31f; 实践出真知&#xff0c;聊聊 HTTP 鉴权那些事 注&#xff1a;此处主要讲的是…

文件服务器鉴权,服务鉴权

使用kmse实现服务的权限校验 通过一个简单的实例说明开发者如何通过kmse进行服务间的权限校验。 一、准备客户端和服务端两个demo 这里演示如何快速实践服务鉴权功能。假如现在有两个微服务 auth-client 和 auth-server&#xff0c;想实现 auth-client 调用 auth-server 时&…

前后端常见的几种鉴权方式

最近在重构公司以前产品的前端代码,摈弃了以前的session-cookie鉴权方式,采用token鉴权,忙里偷闲觉得有必要对几种常见的鉴权方式整理一下。 目前我们常用的鉴权有四种: HTTP Basic Authenticationsession-cookieToken 验证OAuth(开放授权)一.HTTP Basic Authentication 这…

鉴权的4种基本方法

一、基于服务器常出现的问题 Seesions&#xff1a; 每次认证用户发起请求时&#xff0c;服务器需要去创建一个记录来存储信息。当越来越多的用户发请求时&#xff0c;内存的开销也会不断增加。 可扩展性&#xff1a; 由于sessions存放在服务器内存中&#xff0c;伴随而来的是可…

什么是鉴权?一篇文章带你了解postman的多种方式

目录 一、什么是鉴权&#xff1f; 二、postman鉴权方式 一、什么是鉴权&#xff1f; 鉴权也就是身份认证&#xff0c;就是验证您是否有权限从服务器访问或操作相关数据。发送请求时&#xff0c;通常必须包含相应的检验参数以确保请求具有访问权限并返回所需数据。通俗的讲就…

10 分钟带你了解鉴权那些事

前言&#xff1a; 鉴权是自动化测试路上的拦路虎&#xff0c;相信大部分同学都深有体会&#xff0c;今天我们就讲一讲这个鉴权到底是怎么回事。 一、什么是鉴权&#xff0c;为什么要鉴权 鉴权&#xff1a;是指是指验证用户是否拥有访问系统的权利。为什么要鉴权&#xff1a;…

常见的鉴权方式简述

一、什么是鉴权&#xff0c;为什么要鉴权 鉴权&#xff1a;是指验证用户是否有访问系统的权利。 为什么要鉴权 &#xff1a;对用户进行鉴权&#xff0c;防止非法用户占用网络资源&#xff0c;非法用户接入网络&#xff0c;被骗取关键信息 二、鉴权方式 Basic Auth basic au…

笔记——什么是鉴权

前言 鉴权是自动化测试路上的拦路虎&#xff1b;故以此记录鉴权到底是怎么回事。 一、什么是鉴权&#xff0c;为什么要鉴权 鉴权&#xff1a;是指验证用户是否有访问系统的权利。为什么要鉴权 &#xff1a;对用户进行鉴权&#xff0c;防止非法用户占用网络资源&#xff0c;非…

ftok()函数解析

ftok 消息队列、信号灯、共享内存常用在Linux服务端编程的进程间通信环境中。而此三类编程函数在实际项目中都是用System V IPC函数实现的。System V IPC函数名称和说明如下表15-1所示。 表15-1 System V IPC函数 消息队列 信号灯 共享内存区 头文件 <sys/msg.h> …

ftok()函数的使用

在上一篇文章中&#xff0c;Mayuyu讲述了共享内存的原理以及使用方法。在创建共享内存之前&#xff0c;必须指定一个ID值&#xff0c;而这个ID值通常是通过现在要讲的ftok()函数得到。ftok()函数原型如下 其中参数fname是指定的文件名&#xff0c;这个文件必须是存在的而且可以…

linux ftok函数的使用

ftok API #include <sys/types.h> #include <sys/ipc.h> key_t ftok(const char *pathname, int proj_id); ftok根据路径名&#xff0c;提取文件信息&#xff0c;再根据这些文件信息及project ID合成key&#xff0c;该路径可以随便设置。该路径是必须存在的&#x…

ftok与fork

ftok函数编辑 系统建立IPC通讯 &#xff08; 消息队列、 信号量和 共享内存&#xff09; 时必须指定一个ID值。通常情况下&#xff0c;该id值通过ftok函数得到。 2ftok原型编辑 头文件 #include < sys/types.h> #include <sys/ipc.h> 函数原型&#xff1a; key_t f…

Linux下的ftok()函数

linux ftok&#xff08;&#xff09;函数 - 清清飞扬 - 博客园 (cnblogs.com) 系统建立IPC通讯&#xff08;如消息队列、共享内存时&#xff09;必须指定一个ID值。通常情况下&#xff0c;该id值通过ftok函数得到。 ftok原型如下&#xff1a; key_t ftok( char * fname, int i…

Linux中ftok函数介绍

函数原型&#xff1a; *key_t ftok(const char fname, int id); 功能&#xff1a;系统建立IPC通讯&#xff08;如消息队列&#xff0c;共享内存时&#xff09;必须指定一个ID值。通常情况下&#xff0c;该id值通过ftok函数得到 返回值&#xff1a;成功返回一个key_t值&#xf…