使用Redis管理登录令牌cookie

相关知识

大多数网站都会使用 cookie 记录用户的身份。cookie 是由少量数据组成的字符串(通常还要经过加密)。网站会要求浏览器存储这些数据,并在向服务端发起请求时将这些数据传回给服务端。

通常,用于处理登录(识别用户身份)的 cookie 分为两种:

  • 签名式 cookie
    • 存储包含用户 ID 等可直接识别用户的信息
    • 附加一个签名,核对 cookie 信息是否被恶意篡改
  • 令牌式 cookie
    • 存储一个随机字符串(令牌)
    • 通过在服务端的数据库中查找随机字符串和用户的对应关系识别用户身份

这两种 cookie 各有优缺,我们可以通过一个表格对比两者的优缺:

类型优点缺点
签名式 cookie直接存储用户信息,方便验证用户身份;可以包含额外信息;对 cookie 进行签名较简单遗漏签名会导致安全漏洞,加密方法不当会泄露用户敏感信息
令牌式 cookiecookie 体积小,可加快通信速度需要使用数据库存储令牌,会造成额外开销

为了避免安全漏洞,本关卡中,我们使用令牌式 cookie

这篇文章将教会你掌握:1.如何核对令牌,2.如何更新令牌,3.如何定期清理无用信息。

如何核对令牌

前面提到了令牌式 cookie 的最大缺点就是会造成额外开销。大多数关系型数据库在每台数据库服务器上只能插入、更新或删除 200 - 2000 个数据行/秒。当网站的负载变高时,数据库就成为了瓶颈。所以,我们需要使用 Redis 取代关系型数据库,存放令牌。

首先,我们约定令牌的存储方式。我们使用一个哈希存储登录令牌与用户的映射关系,其中:

  • 哈希键名为 login
  • 登录令牌作为
  • 用户 ID 作为

所以核对令牌就变得十分简单,方法如下:

import redisconn = redis.Redis()def check_token(token):
return conn.hget('login', token)

我们使用 hget() 方法从 Redis 中取出并返回令牌对应的用户 ID,而**当令牌不存在时,该方法则会返回 None**,从而达到核对检查的效果。

如何更新令牌

更新令牌需要做两个工作:

  • 记录用户令牌
  • 记录令牌生成时间

由于令牌存在被人窃取的可能,所以我们不允许令牌永不过期。通过记录令牌生成的时间戳,我们可以通过定期清理的方式,清理掉一定时间前生成(过老)的令牌,从而实现令牌的时限性,在一定程度上也减少了 Redis 的存储量,避免内存过高消耗。

使用有序集合记录令牌生成时间能让我们更便捷的根据时间戳对令牌进行排序,然后再对一定时间前生成(过老)的令牌进行删除。将时间戳作为分值,令牌作为成员,记录到有序集合 recent:token 中:

import timetimestamp = time.time() #返回当前时间的时间戳(1970年后经过的浮点秒数)
conn.zadd('recent:token', token, timestamp)

而记录用户令牌可以使用 hset() 方法,将 tokenuser_id 的域-值对关系记录到哈希中:

conn.hset('login', token, user_id)

上述两个操作是相关的,记录了用户令牌则应该也有对应的令牌生成时间,所以我们应该使用事务将两条命令包起来,最后一起提交给 Redis 处理:

def update_token(token, user_id):
timestamp = time.time()
pipe = conn.pipeline()
pipe.hset('login', token, user_id)
pipe.zadd('recent:token', token, timestamp)
pipe.execute()
如何定期清理无用信息

随着登录用户的增多,令牌存储所需的内存也会不断增加,这时,我们需要定期清理过期的令牌数据。

决定令牌的有效时间需要权衡数据安全与用户体验两方面:

  • 有效时间过短,则用户需要频繁的输入账户密码登入系统
  • 有效时间过长,则令牌泄露的可能性增大,伪造用户身份的可能性也越大

综合上述两个方面的考虑,我们将令牌的有效时间设置为一个星期(86400秒),在每次清理令牌数据时,我们找到令牌生成时间在一个星期前的数据,并将这些令牌和令牌生成时间数据全部删除。

寻找一个星期前生成的令牌是关键,我们可以使用当前 Unix 时间减去 86400 得到一个星期前的 Unix 时间戳,然后使用有序集合命令 ZRANGEBYSCORE 获取有序集合 recent:token 中所有分值(生成时间)大于等于 0,小于等于一个星期前的 Unix 时间戳的成员:

one_week_ago_timestamp = time.time() - 86400exipred_tokens = conn.zrangebyscore('recent:token', 0, one_week_ago_timestamp)

接下来,我们要从有序集合 recent:token 中删除掉 expired_tokens 的所有成员,以及从哈希 login 中移除所有过期的 token 域。

为了减少客户端与 Redis 之间的通信次数,我们可以直接使用 ZREMRANGEBYSCORE 命令移除有序集合 recent:token 中所有分值(生成时间)大于等于 0,小于等于一个星期前的 Unix 时间戳的成员:

conn.zremrangebyscore('recent:token', 0, one_week_ago_timestamp)
conn.hdel('login', *expired_tokens)

我们使用了 hdel() 方法一次性从哈希 login 中移除了所有过期的 token 域,由于 expired_tokens 是一个数组,而客户端会默认将输入的值转换为字符串,所以我们在这里要使用 *expired_tokens,以指针的形式调用 expired_tokens 变量,传入多个参数(域)

让清理方法自动执行

你可以使用守护进程的方式来保证这个方法始终在运行,也可以通过定时任务(cron job每隔一段时间执行一次

因为这些知识超出了本实训的讲解范围,在这里就不再详述。

编程要求

根据提示,在右侧Begin-End区域补充代码,完成令牌管理的后端处理逻辑:

  • 在 check_token(token) 方法中:
    • 使用 hget() 方法从哈希 login 中取出参数 token 域的值
    • 返回(return)上述值
  • 在 update_token(token, user_id) 方法中:
    • 参数说明:
      • token 为令牌
  • user_id 为该令牌对应的用户 ID
    • 获得当前时间并赋值给 timestamp
    • 使用事务提交下列命令:
      • 将域 token 与值 user_id 对存入哈希键 login 中
  • 将成员 token 存入有序集合 recent:token 中,分值为 timestamp
  • 在 clean_tokens() 方法中:
    • 使用当前时间减去 86400 得到一周前时间戳,并赋值给 one_week_ago_timestamp
    • 使用 zrangebyscore 方法获取有序集合 recent:token 中
      • 分值大于等于 0
  • 小于等于 one_week_ago_timestamp 的所有成员
  • 并赋值给变量 expired_tokens
    • 使用 zremrangebyscore 方法移除有序集合 recent:token 中
      • 分值大于等于 0
  • 小于等于 one_week_ago_timestamp 的所有成员
    • 移除哈希 login 中所有与变量 expired_tokens 中相同的域
      • 使用指针形式传入参数 *expired_tokens

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

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

相关文章

AI Agent 结构与分类

一、什么是AI agent 在人工智能中,智能代理AI Agent是以智能方式行事的代理;它感知环境,自主采取行动以实现目标,并可以通过学习或获取知识来提高其性能。人其实就是一种复杂代理。 为了理解智能代理的结构,我们应该熟…

前后端数据传输格式(下)

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO 联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬 上篇主要复习了HTTP以及…

时间序列预测实战(二十三)进阶版LSTM多元和单元预测(课程设计毕业设计首选)

一、本文介绍 本篇文章给大家带来的是利用我个人编写的架构进行LSTM模型进行时间序列建模(专门为了时间序列领域新人编写的架构,简单且不同于市面上大家用GPT写的代码),包括结果可视化、支持单元预测、多元预测、模型拟合效果检测…

Android : ViewModel_解决textView 横竖屏数据丢失

横竖屏切换 textView 数据丢失 1.导包 // 使用androidx版本库implementation androidx.lifecycle:lifecycle-extensions:2.1.0-alpha03// 或者,使用support版本库implementation android.arch.lifecycle:extensions:1.1.1 2.写个类 继承 viewModel import an…

文字处理工具Word mac软件特点

Microsoft Word mac是一款文字处理软件。它是 Microsoft office 套件的一部分,已广泛用于创建、编辑和格式化文本文档。 Word mac软件特点 改进的协作工具:使用 Microsoft Word 2021,多个用户可以同时处理一个文档,从而更轻松地与…

记录111

在两台 RHEL 8 服务器上搭建 PostgreSQL 和 pgpool-II 环境涉及到安装 PostgreSQL、配置流复制(Streaming Replication)以及安装和配置 pgpool-II。以下是详细的步骤: ### 准备工作 1. **获取服务器**:确保你有两台运行 RHEL 8 的…

EasyRecovery2024免费永久版手机数据恢复软件

EasyRecovery2024是一款操作安全、用户可自主操作的数据恢复方案,它支持从各种各样的存储介质恢复删除或者丢失的文件,其支持的媒体介质包括:硬盘驱动器、光驱、闪存、硬盘、光盘、U盘/移动硬盘、数码相机、手机以及其它多媒体移动设备。能恢…

bad_python

攻防世界 (xctf.org.cn) 前戏 下载文件,解压完成后是这个 一个pyc文件 这里要用到python的反编译 要用到的工具有两个 1.python自带的uncompyle6 2.pycdc文件——比uncompyle6强大一点 我们一个一个来尝试一下 uncompyle6: 我是直接在pycharm里面…

Stm32 CubeIDE对RTC的日期、时间读写,后备存储的读写

Stm32 CubeIDE对RTC的日期、时间读写,后备存储的读写,一折腾又是好多的问题,现在梳理一下,后面的不要过多踩坑了。 用STM32CubeIDE生成代码 这里有时间和日期的设置,在代码中也会生成相应的代码,首次设置后…

Spark读写Doris数据

1 准备Spark环境 创建maven工程,编写pom.xml文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocati…

文字识别(OCR)专题——基于NCNN轻量级PaddleOCRv4模型C++推理

前言 PaddleOCR 提供了基于深度学习的文本检测、识别和方向检测等功能。其主要推荐的 PP-OCR 算法在国内外的企业开发者中得到广泛应用。在短短的几年时间里&#xff0c;PP-OCR 的累计 Star 数已经超过了32.2k&#xff0c;常常出现在 GitHub Trending 和 Paperswithcode 的日榜…

第二节JavaScript 语法、语句、注释、变量、数据类型等

一、JavaScript语法 1、JavaScript字面量 数字&#xff08;Number&#xff09;字面量&#xff1a;可以是整数或者是小数、或者是科学计数。 如&#xff1a;3.14 、1001 、123e5 字符串&#xff08;String&#xff09;字面量&#xff1a;可以使用单引号或双引号。 例如&…

Linux:/dev/mapper/centos-root 100%问题

思路1 切换到 / 目录下&#xff0c;看下是哪个目录占用的比较大 cd / du -h -x --max-depth1 思路2 直接查找大文件&#xff0c;查找大于100m的文件&#xff0c;可以根据实际情况&#xff0c;适当调整查找的文件大小 find / -type f -size 100M 思路3 使用lsof命令查看是否有占…

springboot(ssm房屋租赁系统 在线租房平台Java(codeLW)

springboot(ssm房屋租赁系统 在线租房平台Java(code&LW) 开发语言&#xff1a;Java 框架&#xff1a;ssm/springboot vue JDK版本&#xff1a;JDK1.8&#xff08;或11&#xff09; 服务器&#xff1a;tomcat 数据库&#xff1a;mysql 5.7&#xff08;或8.0&#xff09…

【算法】算法题-20231205

这里写目录标题 一、LCS 01. 下载插件二、已知一个由数字组成的列表&#xff0c;请将列表中的所有0移到右侧三、实现一个trim()函数&#xff0c;去除字符串首尾的空格&#xff08;不能使用strip()方法&#xff09; 一、LCS 01. 下载插件 简单 小扣打算给自己的 VS code 安装使…

FileIUtils 最佳实践

import java.io.File; import java.io.IOException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter;public class FileIUtils {删除文件夹及文件夹下的所有文件 public static void deleteDirAndFiles(String path) throws Exception {File fil…

全球与中国仿制药市场:增长趋势、竞争格局与前景展望

仿制药是指在剂型、功效、给药方法、品质、性能特征、用途等方面与原厂药相似并已获得原厂药上市许可的药品。仿制药的价格低于品牌药。糖尿病、癌症和心血管疾病等慢性疾病的快速成长推动了仿制药市场的成长。此外&#xff0c;仿制药的实惠价格以及最新产品的批准和推出也有助…

ViVo小游戏对接sdk

1.安装环境&#xff1a; 电脑环境&#xff1a;adb环境和oppo一样&#xff0c;npm环境和oppo一样 升级npm&#xff1a; npm install -g npm 清除npm缓存&#xff1a;npm cache clean -f 安装vivo初始化小游戏的工具&#xff1a; npm install -g vivo-minigame/cli 解决办法&…

前端知识笔记(三十四)———HBuilder的下载与使用(详细步骤)

一、HBuilder IDE的下载 HBuilder下载官网地址&#xff1a; 在地址栏中直接输入https://www.dcloud.io 或者直接点击下面的链接 DCloud - HBuilder、HBuilderX、uni-app、uniapp、5、5plus、mui、wap2app、流应用、HTML5、小程序开发、跨平台App、多端框架 进入官网&#x…

[ 蓝桥杯Web真题 ]-外卖给好评

目录 介绍 准备 目标 效果 规定 思路 解答参考 介绍 外卖是现代生活中必备的一环。收到外卖后&#xff0c;各大平台软件常常会邀请用户在口味&#xff0c;配送速度等多个方面给与评分。在 element-ui 组件中&#xff0c;已经有相应的 Rate 组件&#xff0c;但是已有组件…