令牌桶 客户端请求_使用刷新的令牌和cookie进行安全的客户端身份验证

2023-11-07

令牌桶 客户端请求

To start off, this is my first article here. I’ve thought about writing it for a while now. Ever since we planned and implemented what we call a moderately secure way to actually authenticate client-side requests against our API where authentication tokens are refreshed and old ones are rapidly expired.

要开始了,这是我在这里的第一篇文章。 我已经考虑过写一段时间了。 自从我们计划并实施了所谓的中度安全方式,即根据我们的API对客户端请求进行实际身份验证,在该API中,身份验证令牌会更新,而旧令牌则会快速过期。

I thought I’d share the idea. I will not be diving into much detail here by using big code examples.

我以为我会分享这个想法。 在这里,我不会通过使用大型代码示例来详细介绍。

LocalStorage与Cookie (LocalStorage vs. Cookies)

We use JSON Web Tokens as authentication tokens. Tokens are generated when the user logs in with his credentials and contains information such as his username (or id). More about the payload below.

我们使用JSON Web令牌作为身份验证令牌。 当用户使用其凭据登录时会生成令牌,其中包含诸如用户名(或ID)之类的信息。 有关以下有效负载的更多信息。

This token needs to be stored somewhere on the client side. After doing some research, we came to the conclusion that LocalStorage is not secure as a token storage. As it is a client-side, persistent storage (does not get cleared unless programmatically told to or when the user clears their browser cache), it can be accessed by other sites as well. So it was a no-go to store tokens.

该令牌需要存储在客户端的某个位置。 经过研究,我们得出的结论是LocalStorage作为令牌存储并不安全 。 由于它是客户端的持久性存储(除非以编程方式告知用户或当用户清除其浏览器缓存时,否则不会清除它),其他站点也可以访问它。 因此,存储令牌是不可行的。

Cookies are considered to be more secure. But only if they contain the proper flags. So of course for us this meant HttpOnly, Secure etc. However, JavaScript does not have an API for HttpOnly cookies. They are not accessible to scripting languages.

Cookies被认为更安全。 但前提是它们包含正确的标志。 因此,对我们来说,这当然意味着HttpOnly,Secure等。但是,JavaScript没有用于HttpOnly cookie的API。 脚本语言无法访问它们。

So what does this mean? It meant that our API had to handle the authentication cookie.

那么这是什么意思? 这意味着我们的API必须处理身份验证Cookie。

用于处理HttpOnly cookie的API (API to handle HttpOnly cookies)

This proved to be great for us. It meant that our front-end does not have to handle anything cookie related. Why did we not think of this from the start?

事实证明,这对我们来说很棒。 这意味着我们的前端不必处理任何与c​​ookie相关的事情。 为什么我们从一开始就没有想到这一点?

The client just has to call an endpoint with the username and password, and if it gets a successful response (200 OK), you know the cookie exists and your subsequent requests can be authenticated.

客户端只需要使用用户名和密码来调用端点,并且如果它获得成功的响应(200 OK),您就知道该cookie存在并且可以对您的后续请求进行身份验证。

So the cookie has to be set in the API’s response.

因此必须在API的response中设置cookie。

使用PSR-7响应的响应cookie的简单PHP示例: (Simple PHP example of a response cookie using PSR-7 response:)

We use PHP as our back-end language and Slim Framework for our REST API. To handle cookies, we installed FIG Cookies as PSR-7 compliant cookie manager. A cookie inserted in the response, from your controller, looks like this:

我们使用PHP作为后端语言,并使用Slim Framework作为REST API。 为了处理cookie,我们将FIG Cookies安装为符合PSR-7的cookie管理器。 来自控制器的响应中插入的Cookie如下所示:

$response = FigResponseCookies::set($response,
SetCookie::create('token')
->withValue($jwt) # Authentication token
->withDomain('example.com')
->withPath('/')
->withExpires(time() + (60 * 45))
->withSecure(true)
->withHttpOnly(true)
->withSameSite(SameSite::strict())
);

So, when the client makes a POST call to /user/login, we first check if the username and password are valid and if they are, we return a response with the cookie in it. Very simple.

因此,当客户端对/user/login进行POST调用时,我们首先检查用户名和密码是否有效,如果有效,我们将返回其中包含cookie的响应。 很简单。

JSON Web令牌 (JSON Web Tokens)

Now, the cookie contains a token. I won’t go into detail about JWT’s. What I will explain, though, is that they contain a payload with information such as your username, and an expiration time. The payload is in JSON format.

现在,cookie包含一个令牌。 我不会详细介绍JWT。 不过,我将解释的是它们包含一个有效负载,其中包含诸如用户名和到期时间之类的信息。 有效负载为JSON格式。

{
"username": "john.doe@example.com"
"exp": 1516239022
}

有效载荷 (Payload)

Now, your payload is publicly readable. You can test tokens at jwt.io if you want. Just paste the generated token there and read it’s payload. Because to this, you cannot store sensitive data inside your payload! What we have there is just the username and expiration time.

现在,您的有效载荷是公开可读的。 您可以根据需要在jwt.io上测试令牌。 只需将生成的令牌粘贴到此处并读取其有效载荷即可。 因此,您不能在有效负载中存储敏感数据! 我们所拥有的只是用户名和有效时间。

期满 (Expiration)

We set our token (not just cookie) expiration to 45 minutes. Enough for you to log in, maybe grab lunch, get back to using the app. Some people consider this to be too long. To an attacker, who somehow gains access to your token, this is enough time to actually log in imposing as you and start reading your data. I will return to this further down.

我们将令牌 (不仅仅是cookie)的有效期设置为45分钟。 您已经足够登录,也许可以享用午餐,然后重新使用该应用程序。 有人认为这太长了。 对于以某种方式可以访问您的令牌的攻击者来说,这是足够的时间来实际登录强加给您并开始读取数据。 我将进一步讨论这一点。

刷新令牌 (Refreshing tokens)

So the token is only valid for 45 minutes there. After that the user gets logged out. That’s not gonna work. We need to refresh the token with each valid request (middleware does the signature validation).

因此令牌仅在此处有效45分钟。 之后,用户将注销。 那是行不通的。 我们需要用每个有效的请求刷新令牌(中间件执行签名验证)。

We created an afterware to refresh the token. This afterware gets the token from the request, modifies the token by taking its payload, refreshing the expiration property, and returning a new token in the response, inside the same cookie. So now you have a new, refreshed, token with each request you make.

我们创建了一个固件来刷新令牌。 此后件从请求中获取令牌,通过获取其有效载荷,刷新expiration属性并在响应中的同一cookie内返回新令牌来修改令牌。 因此,现在您对每个请求都有一个新的,刷新的令牌。

Here is an example of such an afterware:

这是一个此类固件的示例:

<?php
namespace App\Middleware;
use Dflydev\FigCookies\FigResponseCookies;
use Dflydev\FigCookies\SetCookie;
use Firebase\JWT\JWT;
use Slim\Http\Request;
use Slim\Http\Response;
final class RefreshTokenExpirationMiddleware {
public function __invoke (Request $request, Response $response, $next) {
# Rewind to get response
$response = $next($request, $response);
$response->getBody()->rewind();
# Pick up the current token (already decoded by the middleware)
$token = $request->getAttribute('auth_token');
if($token) {
# Add 45 minutes to token
$token['exp'] = time() + (60 * 45);
# New token
$encoded = JWT::encode($token, 'secret', ['HS256']);
$modify = function(SetCookie $setCookie) use ($encoded) {
return $setCookie->withValue($encoded)->withExpires(time() + (60 * 45));
};
$response = FigResponseCookies::modify($response, 'auth_token', $modify);
}
return $response;
}
}

将令牌列入白名单 (Whitelisting tokens)

So returning to the expiration; 45 minutes is a big gap. And we are creating more and more tokens with each request! This creates a nice little pile of valid tokens a possible attacker can grab and use. It’s a problem.

回到到期日; 45分钟是一个很大的差距。 而且,每个请求都将创建越来越多的令牌! 这会产生一小堆有效的令牌,可能的攻击者可以抓住并使用。 这是一个问题。

So what we did is we found a nice idea online of a blacklist. However, we made it a whitelist.

因此,我们所做的就是在网上找到了一个黑名单的好主意。 但是,我们将其列入了白名单。

When the user logs in, and the first token is created, that token gets placed inside a whitelist container that resides in Redis with a TTL (Time to Live) of 45 minutes. A simple storage, but with automatic expiration.

当用户登录并创建第一个令牌时,该令牌将放入白名单容器中 ,该容器位于Redis中 ,其TTL (生存时间)为45分钟。 一个简单的存储,但具有自动到期时间。

We already had one middleware in place to check if the token’s signature is valid. We then created another middleware that checks if the token is still inside the whitelist. (Sorry, no code examples here, just an explanation).

我们已经有一个中间件来检查令牌的签名是否有效。 然后,我们创建了另一个中间件,用于检查令牌是否仍在白名单中。 (对不起,这里没有代码示例,只是一个解释)。

If the signature is OK and the token is still whitelisted, the request moves forward. Otherwise you get a 401 Unauthorized response.

如果签名确定,并且令牌仍被列入白名单,则请求将继续进行。 否则,您将收到401 Unauthorized回复。

Now, after the request has been completed the afterware mentioned earlier takes the token you just made the request with, and rapidly expires it. It gets deleted from the whitelist and then put back in with a 5 min TTL. The newly refreshed token gets inserted there with a 45 min TTL.

现在,在请求完成后,前面提到的固件将使用您刚刚发出请求的令牌,并Swift使该令牌过期。 它会从白名单中删除,然后以5分钟的TTL恢复。 新刷新的令牌将以45分钟的TTL插入那里。

With this, you have a valid token with 45 min expiration and any older ones with a 5 min expiration. You just made the window of a possible attack that much more narrow.

这样,您将拥有一个有效的令牌,其有效期为45分钟,而任何较旧的令牌的有效期为5分钟。 您只是将可能的攻击范围缩小了很多。

Authentication flow diagram
认证流程图

其他安全措施 (Additional security measures)

So now, you might be thinking that the 45 minutes is still an open window there. An additional security measure would be to actually log the IP-addresses of each token request and check that the requests originate from the same address subsequently. If a mismatch is detected between requests the user is signed out and forced to log back in.

所以现在,您可能会认为45分钟仍然是一个打开的窗口。 另一安全措施是实际记录每个令牌请求的IP地址,并随后检查请求是否源自同一地址。 如果在请求之间检测到不匹配,则用户将注销,并被迫重新登录。

You can maybe do the same for other information as well. You ever seen those warnings Google sends you when they detect you logged in from a new IP-address or machine? There’s an idea.

对于其他信息,您也可以执行相同的操作。 您曾经看过Google向您发送的那些警告,因为它们检测到您是从新IP地址或计算机登录的吗? 有个主意

翻译自: https://medium.com/@rcls/secure-client-side-authentication-using-refreshed-tokens-and-cookies-4dacc0bc8ff0

令牌桶 客户端请求

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

令牌桶 客户端请求_使用刷新的令牌和cookie进行安全的客户端身份验证 的相关文章

  • java替代Thread.stop()来中断特定调用

    我正在寻找一种方法来告诉这个调用 大约需要 20 120 秒 final Area image final AffineTransform transform new AffineTransform transform scale imag
  • 将 JSON Map 传递到 Spring MVC 控制器

    我正在尝试将 Map 的 JSON 表示形式作为 POST 参数发送到我的控制器中 RequestMapping value search do method RequestMethod GET consumes application j
  • 获取TextView的高度

    我有一些文字将被放入TextView 我这样做是使用setText 现在我需要找到文本在文本中占据的行数或高度TextView 我尝试使用getHeight 但它总是返回 0 无论如何 有没有办法获得文本中存在的文本的高度TextView
  • 我需要显式关闭连接吗?

    我持有一个实例MongoClient and DB在我的应用程序中 每次我想执行某些操作时 我都会调用getCollection 我想知道是否需要显式关闭连接 就像connection close 在 JDBC 中 强调一下 我只有一个Mo
  • 总结二维数组

    鉴于我当前的程序 我希望它在用户输入所有值后计算每列和每行的总和 我当前的代码似乎只是将数组的值加倍 这不是我想要做的 例如 如果用户输入具有以下值 1 2 3 2 3 4 3 4 5 的 3x3 矩阵 则看起来就像我在下面的程序中对其进行
  • 确定代码是否在 App Engine 运行时 (Java) 上运行

    如何确定某些代码 Serv let 或简单的类 是否正在 Google App Engine 运行时 Java 上运行 以便决定是否使用 App Engine 的特定库 是否有一些可靠的运行时环境 ID 您可以检查com google ap
  • 在java.util中获取错误ArrayList不带参数[重复]

    这个问题在这里已经有答案了 我已经创建了一个类 Student 现在我尝试将我的 Student 对象存储在 ArrayList 中 但在编译 ArrayList 不接受参数时出现错误 我已经检查了我的代码很多次 但找不到问题所在 我的学生
  • 给定一个单词列表 - 在 java 中完成单词的好的算法是什么?权衡:速度/效率/内存占用

    我正在探索潜在的免费 付费应用程序的硬件 软件要求 最终目标是移动 Java 应用程序 该应用程序将从这个简单的目标开始 给定数据库中相关单词的列表 能够对单个字符串输入进行单词补全 换句话说 我已经知道数据库的内容 但算法的内存占用 速度
  • activemq 的优先级

    我们目前正在使用 JMS 和 activemq 5 5 1 开发一个应用程序 我们想为某些消息定义更高的优先级 这将使它们首先被消耗 设置生产者和消费者后 通过spring 3 1 JMSTemplate 优先级并不能完全发挥作用 事实上
  • Java中无参数的for循环

    我在看别人的代码 发现了这段代码 for 我不是 Java 专家 这行代码在做什么 起初 我认为这会创建一个无限循环 但在该程序员使用的同一个类中 while true 其中 如果我错了 请纠正我 是一个无限循环 这两个相同吗 为什么有人会
  • 使用 include 进行 JAXB 剧集编译不起作用

    我有 2 个模式 A B 我在 B 中重用了一些 A 元素 我不使用命名空间 我在用着
  • 我可以关闭并重新打开套接字吗?

    我学习了一个使用套接字的例子 在此示例中 客户端向服务器发送请求以打开套接字 然后服务器 侦听特定端口 打开套接字 一切都很好 套接字从双方 客户端和服务器 打开 但我仍然不清楚这个东西有多灵活 例如 客户端是否可以关闭一个打开的 从两端
  • 链表中的虚拟节点

    问 什么时候使用它们 作业问题 列表中的第一个和最后一个节点 有时用作列表中的第一个和最后一个节点 从未用作列表中的第一个和最后一个节点 维基百科说 哨兵节点是与链接一起使用的专门指定的节点 列表和树作为遍历路径终止符 哨兵节点的作用是 不
  • Storm Spout 未收到 Ack

    我已经开始使用storm 所以我使用创建简单的拓扑本教程 https github com nathanmarz storm wiki Tutorial 当我运行我的拓扑时LocalCluster一切看起来都很好 我的问题是我没有得到元组的
  • Microsoft JDBC 中的 JTDS 属性相当于什么?

    我正在将 JTDS 连接更改为 Microsoft JDBC 并且我看到存在于http jtds sourceforge net faq html http jtds sourceforge net faq htmlMicrosoft JD
  • Java 相当于 Python 的 urllib.urlencode(基于 HashMap 的 UrlEncode)

    From https stackoverflow com questions 2018026 should i use urllib or urllib2 2018103 2018103 Java 中 Python 的 urllib url
  • Python 可以替代 Java 小程序吗?

    除了制作用于物理模拟 如抛射运动 重力等 的教育性 Java 小程序之外 还有其他选择吗 如果你想让它在浏览器中运行 你可以使用PyJamas http pyjs org 这是一个 Python 到 Javascript 的编译器和工具集
  • 将带有时区的 Joda-Time `DateTime` 转换为没有时区的 DateTime?

    Given a DateTime http www joda org joda time apidocs org joda time DateTime html例如2015 07 09T05 10 00 02 00 using 乔达时间 h
  • Java,如何管理线程读取socket(websocket)?

    我有一个 WebSocket 服务器 我的服务器创建一个新线程来处理新连接 该线程一直处于活动状态 直到 websocket 中断 我的问题 对于 1 000 000 个连接 我需要 1 000 000 个线程 我如何通过一个线程处理多个
  • 使用 Hibernate 防止无限循环数据检索

    我想知道 想象一个场景 例如 POJO public class User private String userName private String name private String surname private List

随机推荐

  • STM32 开机一直进IDLE空闲中断的解决思路

    串口IDLE空闲中断 常用于串口DMA IDLE中断接收不定长数据 一开始玩DMA 调试程序在一直进入IDLE中断时候 可能是没有软件清零 STM32中文参考手册这么描述的 IDLE 检测到空闲线路 IDLE line detected 检
  • 热更新_ToLua学习示例 06_LuaCoroutine2

    function CoExample WaitForSeconds 1 作者封装的协程等待一秒 print WaitForSeconds end time UnityEngine Time time WaitForFixedUpdate 等
  • cas单点登录系列1.3:自定义登录页

    cas单点登录系列1 3 自定义登录页 cas提供登录页比较大众 我们根据需求进行自定义 所以本节会介绍登录页的一些内容 比较简单 大家可根据情况进行学习 文章目录 cas单点登录系列1 3 自定义登录页 前言 一 登录页组成 二 登录接口
  • java中使用jxls导出excel,excel单元格换行,多sheet页导出

    一 模板 jxls通过模板中的批注语法来渲染数据 所以写好模板已经成功了一大半 我的模板如下 这里我定义了两个sheet页 第一个sheet页就是汇总的 直接取数据遍历 第二个sheet页就是动态sheet页的模板 注意模板作用域的定义一定
  • Python总复习——简答题篇

    简答题篇 1 简述元祖 列表和字典的区别 2 简述局部变量和全部局变量的区别 3 简述闭包满足的三个条件 4 简述导入模块的方法 1 简述元祖 列表和字典的区别 名称 外形 存储结构 访问方式 是否可变类型 列表 中括号括起来的数据 可以存
  • 软件测试工程师技术发展规划 (2022初稿)

    软件测试工程师技术发展规划 2022 2022年3月18日22 19 04 1 不同Level的技术标准 1 1 级别一 测试工程师TE 1 1 1 主要工作内容 1 2 级别二 测试开发工程师 1 2 1 主要工作内容 1 2 2 工作组
  • Java中static关键字详解

    1 1概述 static是静态修饰符 什么叫静态修饰符呢 大家都知道 在程序中任何变量或者代码都是在编译时由系统自动分配内存来存储的 而所谓静态就是指在编译后所分配的内存会一直存在 直到程序退出内存才会释放这个空间 也就是只要程序在运行 那
  • Azure Blob Storage 基本用法上传/下载(Java)

    文章目录 简单概念 Blob Storage Azure Blob Storage的存储结构 Azure Storage Account Container Blob 操作 Maven依赖 创建Container对象 获取Blob列表 下载
  • 图像识别最好的算法,图片相似度识别算法

    现在人脸识别最有效的算法是什么 最好的人脸识别系统在理想情况下比人类识别的表现要好的多 但是一旦环境情况变糟 系统的表现就差强人意了 而计算机科学家们当然是非常想要开发出一种算法 在各种情况下都能够表现优异 现在 中国香港大学的汤晓鸥教授和
  • Three.js3D可视化介绍,以及本地搭建three.js官网

    一 什么是Three js three js官网 https threejs org Three js是一个基于WebGL的JavaScript 3D图形库 它可以轻松地在浏览器中创建3D场景和动画 同时 它支持外部模型和纹理的导入 让开发
  • Windows Server2012R2 VisualSVN4.2.2-Server在线修改密码搭建

    最近有个3 0 0的svn环境要升级可以web界面自助修改密码的 为了找到这个解决方案 我搜索了很多文章与资料 有不少文章提供的总是各种很隐约 好像它要藏着啥好东西似的 我觉得既然你选择了分享你的成果 那就应该把整个过程整理顺畅 而不是在文
  • python解决数组奇数和偶数位置排序问题

    题目描述 输入一个整数数组 实现一个函数来调整该数组中数字的顺序 使得所有的奇数位于数组的前半部分 所有的偶数位于数组的后半部分 并保证奇数和奇数 偶数和偶数之间的相对位置不变 题目解析 这个题目很简单 只需要判断数组中的元素是奇数还是偶数
  • 生成随机数函数:rand和srand

    头文件为 stdlib h rand 会随机生成一个位于 0 RAND MAX 之间的整数 RAND MAX 是
  • [算法] 深搜整理

    深搜 之前在leetcode上刷题一直都对这个知识点比较模糊 最近 集中写了几道深搜的题目 将自己的思路和题目做了整理写下此篇博客 博客很多题目是网上提供的一些深搜题目 另外一些是leetcode上关于深搜的题目 六角填数 如下图所示六角形
  • 转 C#中的委托和事件 - Part.1

    http www tracefact net tech 009 html C 中的委托和事件 Part 1 2007 9 23 作者 张子阳 分类 C 语言 注意 文中代码在VS2005下通过 由于VS2003 Net Framework
  • jquery mobile实现拨打电话功能

    在做一个便民服务电话 用到移动web中列出的电话 点击需要实现调用通讯录 拨打电话功能 如果需要在移动浏览器中实现拨打电话 发送email 调用sns等功能 jquery mobile提供的接口是一个好办法 采用url链接的方式 实现在Sa
  • mipi-CSI2驱动接口调试 LCD 的CLK时钟频率与显示分辨率及帧率的关系

    锋影 email 174176320 qq com 我们先来看一个公式 Mipiclock width hsync hfp hbp x height vsync vfp vbp x bus width x fps lane num 2 即m
  • 让Unity中的多个模型共用同一个材质球

    如何让Unity中的多个模型共用同一个材质球呢 下面我就来分享一下我之前在做模型的时候所使用的方法和思路 供大家学习 Unity文档中曾明确提到 尽可能的共用Material 这主要是因为渲染引擎一般会按照材质对需要渲染的对象进行排序 同一
  • SCJP认证试题(十三)

    1public class A 2 private int counter 0 3 4 public static int getInstanceCount 5 return counter 6 7 8 public A 9 counter
  • 令牌桶 客户端请求_使用刷新的令牌和cookie进行安全的客户端身份验证

    令牌桶 客户端请求 To start off this is my first article here I ve thought about writing it for a while now Ever since we planned