令牌和签名详细介绍+开发使用教程

令牌和签名简介

1. 令牌(Token)

概念

令牌(Token)是一个用于身份验证的小段数据,通常在用户登录时由服务器生成,并返回给客户端。客户端在后续的请求中将令牌附加到请求头中,服务器通过验证令牌来确认用户身份,并决定是否授权访问请求的资源。

常见类型
  • JWT(JSON Web Token):JWT 是一种非常常见的令牌形式,它以 JSON 格式存储信息,并使用签名来确保其内容的完整性。
  • OAuth 令牌:在 OAuth 2.0 授权框架中,令牌(如访问令牌、刷新令牌)用于授权和认证。
令牌的结构

以 JWT 为例,它由三个部分组成,用点号(.)分隔:

  1. Header(头部):定义了令牌的类型(通常是 “JWT”)和所使用的签名算法(如 HMAC SHA256)。
    {"alg": "HS256","typ": "JWT"
    }
    
  2. Payload(负载):包含声明(Claims),可以包括用户信息、令牌的颁发时间和过期时间等数据。
    {"sub": "1234567890","name": "John Doe","iat": 1516239022
    }
    
  3. Signature(签名):对前两个部分(头部和负载)进行签名,确保其未被篡改。
    HMACSHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)
    
令牌的用途
  • 身份验证:用户在成功登录后获取令牌,并在每次请求时将令牌附加到请求头中(通常是 Authorization: Bearer <token>),服务器通过验证令牌来确认用户身份。
  • 授权:服务器可以通过解析令牌中的信息决定用户是否有权访问特定资源。
令牌的优势
  • 无状态:服务器不需要存储用户的会话信息,因为所有的身份验证信息都包含在令牌中。
  • 安全性:令牌通过签名确保其内容未被篡改,并且可以设置过期时间,限制令牌的有效期。

2. 签名(Signature)

概念

签名(Signature)是通过加密算法生成的,用于确保数据的完整性和来源的真实性。签名通常是对消息的散列值(哈希值)进行加密得到的。签名可以防止数据在传输过程中被篡改。

签名的用途
  • 数据完整性:签名可以验证数据在传输过程中是否被篡改。如果接收到的数据与签名验证结果不匹配,说明数据已被修改。
  • 数据来源验证:签名可以用来确认数据的来源,因为只有拥有签名密钥的实体才能生成正确的签名。
  • 请求保护:在一些系统中,每次请求都会生成一个新的签名,用于保护请求数据不被篡改。
签名的生成

签名的生成过程通常包括以下步骤:

  1. 选择密钥和算法:签名的生成需要一个密钥和算法(如 HMAC、RSA、ECDSA 等)。
  2. 生成散列值:对数据(如请求的参数、时间戳等)生成散列值。
  3. 加密散列值:使用选择的算法和密钥对散列值进行加密,从而生成签名。
签名的验证

签名的验证过程如下:

  1. 提取签名:从请求或数据包中提取签名。
  2. 生成散列值:使用与生成签名时相同的数据生成一个新的散列值。
  3. 加密并比较:将生成的散列值与提取的签名进行加密并比较,如果匹配,则签名有效,数据未被篡改。
签名的应用场景
  • API 请求签名:为了确保 API 请求的完整性,服务器会对每个请求生成签名,客户端发送的请求中包含这个签名,服务器验证签名是否有效。
  • 消息签名:在消息传递系统中,签名用于确保消息未被篡改,并且来自可信来源。

3. 结合令牌和签名的安全机制

在一个系统中,为了确保用户身份验证和数据传输的安全性,可以结合使用令牌和签名:

  • 令牌认证:每次客户端发送请求时,附带上已生成的令牌,服务器通过验证令牌确认用户身份。
  • 签名认证:在访问敏感资源或请求页面时,生成一个签名并发送给服务器,服务器通过验证签名确保请求未被篡改且合法。
流程总结
  1. 用户登录:服务器生成令牌并返回给客户端,客户端存储令牌。
  2. 访问资源:客户端每次访问资源时,发送存储的令牌,并生成一个签名附加到请求中。
  3. 服务器验证:服务器验证令牌和签名,如果验证成功,返回资源数据,否则拒绝请求。

这种机制能够同时确保用户身份的合法性和请求数据的完整性,大大提升了系统的安全性。

使用案例

在前端使用 HTML 或 JavaScript 实现结合令牌和签名的安全验证流程,以下是一个基本的实现方案。

1. 用户登录流程

前端:
  1. 用户输入并提交登录信息:

    <form id="loginForm"><input type="text" id="username" placeholder="Username"><input type="password" id="password" placeholder="Password"><button type="submit">Login</button>
    </form>
    <script>document.getElementById('loginForm').addEventListener('submit', async function(event) {event.preventDefault();const username = document.getElementById('username').value;const password = document.getElementById('password').value;// 向服务器发送登录请求const response = await fetch('/api/login', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify({ username, password })});const result = await response.json();if (result.token) {// 将令牌存储在本地localStorage.setItem('authToken', result.token);} else {alert('Login failed!');}});
    </script>
    
  2. 服务器返回令牌并存储:

    • 令牌成功返回后,存储在 localStorage 中,方便后续请求使用。

2. 访问页面资源的流程

前端:
  1. 生成签名并发出请求:

    function generateSignature(data, secretKey) {// 这里用的是一个简单的加密算法,如有需要可使用更复杂的加密逻辑return btoa(data + secretKey);
    }async function fetchProtectedResource(url) {const token = localStorage.getItem('authToken');if (!token) {alert('Not authenticated!');return;}// 数据可以包括请求URL、时间戳等const requestData = url + new Date().toISOString();const secretKey = 'your_secret_key'; // 注意:实际应用中,密钥不会存在前端const signature = generateSignature(requestData, secretKey);const response = await fetch(url, {method: 'GET',headers: {'Authorization': `Bearer ${token}`,'X-Signature': signature}});const data = await response.json();console.log(data);
    }// 例子:访问受保护资源
    fetchProtectedResource('/api/protected-resource');
    
  2. 服务器验证请求:

    • 服务器收到请求后,从请求头中获取 AuthorizationX-Signature,然后验证令牌和签名。

3. 签名的生成与验证

签名在前端生成,并随请求发送到服务器。服务器使用相同的算法和密钥验证签名。

前端:
function generateSignature(data, secretKey) {return btoa(data + secretKey); // Base64编码
}
服务器:
function verifySignature(receivedSignature, data, secretKey) {const expectedSignature = generateSignature(data, secretKey);return receivedSignature === expectedSignature;
}

4. 关键点

  • 令牌存储安全: 在前端使用 localStoragesessionStorage 存储令牌,但要注意 XSS 攻击。
  • 签名的动态生成: 每次请求都动态生成签名,避免重放攻击。
  • 服务器端验证: 服务器端必须验证令牌和签名的有效性,确保安全。

5. 流程总结

  1. 用户登录: 用户提交用户名和密码,服务器验证后返回令牌,前端存储令牌。
  2. 访问页面资源: 前端在发出请求前,生成签名并携带令牌,服务器验证后返回数据。

通过这种方式,结合令牌和签名,前端和服务器可以共同确保用户的身份验证和请求的完整性,增强系统的安全性。

前端生成签名时,秘钥如何获取?

在前端生成签名时,使用的密钥(secret key)不能直接存储在前端代码中,因为前端代码是公开可见的,任何用户都可以查看源代码。因此,密钥的处理需要特别注意,以确保系统的安全性。

秘钥的获取和使用方法

  1. 使用短期有效的临时密钥:

    • 方案: 当用户成功登录后,服务器生成一个临时密钥并随令牌一起返回给客户端。这个密钥的有效期较短(例如 15 分钟或 1 小时),客户端在生成签名时使用这个临时密钥。
    • 优点: 临时密钥即使被泄露,由于有效期短,攻击者的利用时间也会被大大缩短。
    • 实现: 服务器生成一个随机的、加密的密钥,发送给客户端。客户端存储在 localStoragesessionStorage 中,并在每次请求时使用。

    示例:

    // 登录时获取临时密钥和令牌
    localStorage.setItem('authToken', result.token);
    localStorage.setItem('temporaryKey', result.temporaryKey);
    
  2. 通过 API 动态获取密钥:

    • 方案: 前端在需要生成签名时,通过一个专门的 API 从服务器请求密钥。服务器根据请求内容、令牌等验证信息,生成并返回一个短期有效的密钥。
    • 优点: 密钥只在生成签名时短暂存储,降低了被泄露的风险。
    • 实现: 每次请求前,先通过 API 获取密钥,然后立即生成签名。

    示例:

    async function fetchTemporaryKey() {const token = localStorage.getItem('authToken');const response = await fetch('/api/get-temp-key', {method: 'GET',headers: {'Authorization': `Bearer ${token}`}});const result = await response.json();return result.temporaryKey;
    }async function fetchProtectedResource(url) {const temporaryKey = await fetchTemporaryKey();const requestData = url + new Date().toISOString();const signature = generateSignature(requestData, temporaryKey);// 继续请求过程...
    }
    
  3. 使用服务器端签名:

    • 方案: 前端不生成签名,而是将请求数据发送到服务器,服务器生成签名并返回。前端在后续请求中使用这个签名。
    • 优点: 密钥完全保存在服务器端,安全性最高。
    • 实现: 请求中包含所有需要生成签名的数据,服务器返回签名。

    示例:

    async function fetchSignature(data) {const token = localStorage.getItem('authToken');const response = await fetch('/api/generate-signature', {method: 'POST',headers: {'Authorization': `Bearer ${token}`,'Content-Type': 'application/json'},body: JSON.stringify(data)});const result = await response.json();return result.signature;
    }
    

关键点总结

  • 短期有效性: 临时密钥的有效期应足够短,以防止长期存储导致的安全风险。
  • 动态获取: 密钥的动态获取可以防止密钥在前端的长期暴露。
  • 服务器端控制: 最安全的方式是将签名逻辑放在服务器端处理,前端只负责发送数据和接受签名结果。

通过这些措施,可以有效减少密钥暴露的风险,同时确保请求的完整性和安全性。

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

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

相关文章

鸿蒙 装饰器 @State、@Prop、@Link 等说明

首先要明白什么是“状态变量”?即被状态装饰器(@State、@Prop、@Link、@Provide、@Consume)修饰的变量,比如 @State str : string=; str就是状态变量。状态变量值的改变会引起UI界面重新渲染。 @State @State装饰的变量,是私有的,只能被组件内部访问,在声明时必须指定…

计算机视觉编程 1(图片处理)

目录 灰色度 缩略图 拷贝粘贴区域 调整图像尺寸 旋转图像45 画图线、描点 灰色度 灰度是指图像中每个像素的亮度值&#xff0c;用来描述图像中各个像素的明暗程度。在计算机视觉中&#xff0c;灰度可以通过以下方式来计算&#xff1a; 1. 平均值法&#xff1a;将图像中每…

【Linux】深入探讨Linux进程等待:`waitpid`与`wait`

文章目录 深入探讨Linux进程等待&#xff1a;waitpid与wait API一、waitpid与wait简介1. wait2. waitpid 二、waitpid与wait的实际应用1. 基本用法示例2. 使用 waitpid 处理多个子进程3. 非阻塞等待 三、使用场景 深入探讨Linux进程等待&#xff1a;waitpid与wait API 在Linux…

Java基础——自学习使用(泛型)

一、泛型的定义 泛型的本质是参数化类型&#xff0c;也就是所操作的数据类型被指定为一个参数。 泛型泛指一切类型&#xff0c;能够代表一切类型&#xff0c;是一种在编程中广泛使用的概念&#xff0c;特别是在面向对象编程中。它允许在编写代码时使用类型参数&#xff0c;这些…

WPS Office两个严重漏洞曝光,已被武器化且在野利用

WPS Office作为一款用户基数超过2亿的广泛使用的办公套件&#xff0c;被发现存在两个关键漏洞&#xff08;CVE-2024-7262和CVE-2024-7263&#xff09;&#xff0c;这些漏洞可能导致用户遭受远程代码执行攻击。这两个漏洞的CVSS评分为9.3&#xff0c;表明它们的严重性很高&#…

C++:Opencv读取ONNX模型,通俗易懂

1. 准备 ONNX 模型 假设你已经有一个训练好的 ONNX 模型文件。可以从各类深度学习框架&#xff08;如 PyTorch、TensorFlow&#xff09;中导出 ONNX 模型。例如&#xff0c;下面是一个简单的 PyTorch 模型导出为 ONNX 文件的示例&#xff1a; import torch import torchvisio…

在使用React Hooks中,如何避免状态更新时的性能问题?

在React Hooks中避免状态更新时的性能问题&#xff0c;可以采取以下一些最佳实践&#xff1a; 避免不必要的状态更新&#xff1a; 使用React.memo、useMemo、和useCallback来避免组件或其子组件进行不必要的渲染。 使用useMemo&#xff1a; 对于基于状态或props的复杂计算&…

MES管理系统助力印刷企业实现智能化工艺流程

在印刷这一古老而充满活力的行业中&#xff0c;科技的浪潮正以前所未有的速度重塑着每一个生产环节。随着制造业数字化转型的深入&#xff0c;引入MES管理系统&#xff0c;为印刷企业带来了从原材料入库到成品出库的全流程智能化变革&#xff0c;不仅提升了生产效率&#xff0c…

剪辑小白必看:好用的剪辑工具推荐!

作为一位热爱创作的视频制作者&#xff0c;我尝试过不少剪辑软件&#xff0c;今天我想分享自己对福昕视频剪辑、爱拍剪辑、达芬奇和VSDC Video Editor这四款软件的使用体验。 福昕视频剪辑 链接&#xff1a;www.pdf365.cn/foxit-clip/ 我第一次接触到福昕视频剪辑是在朋友的…

python基础语法2

python基础语法2 了解整体内容可以从基础语法1开始&#xff0c;第2天了&#xff0c;开始上代码片段。 本篇主要内容&#xff1a;控制流语句if、for、match等。 打印及main方法 # 注释使用#号 #打印hello def print_hello(name):#这里加上f是打印变量内容&#xff0c;不加f打印…

树数据结构(Tree Data Structures)的全面指南:深度解析、算法实战与应用案例

树数据结构&#xff08;Tree Data Structures&#xff09;的全面指南&#xff1a;深度解析、算法实战与应用案例 引言 树数据结构&#xff08;Tree Data Structures&#xff09;作为计算机科学中的基石之一&#xff0c;以其独特的层次结构和分支特性&#xff0c;在众多领域发…

2012-2022年各省新质生产力匹配数字经济数据

2012-2022年各省新质生产力匹配数字经济数据 1、时间&#xff1a;2012-2022年 2、来源&#xff1a;各省年鉴、能源年鉴、工业年鉴、统计年鉴 3、指标&#xff1a;prov、year、gdp亿元、在岗职工工资元、第三产业就业比重、人均受教育平均年限、教育经费强度、在校学生结构、…

【STM32】IWDG独立看门狗与WWDG窗口看门狗

本篇博客重点在于标准库函数的理解与使用&#xff0c;搭建一个框架便于快速开发 目录 WDG简介 IWDG IWDG特性 独立看门狗时钟 键寄存器 超时时间 IWDG代码 WWDG WWDG特性 窗口看门狗时钟 超时时间 WWDG时序 WWDG代码 IWDG和WWDG对比 WDG简介 WDG&#xff08;…

面经:什么是Transformer位置编码?

过去的几年里&#xff0c;Transformer大放异彩&#xff0c;在各个领域疯狂上分。它究竟是做什么&#xff0c;面试常考的Transformer位置编码暗藏什么玄机&#xff1f;本文一次性讲解清楚。 Transformer的结构如下&#xff1a; 可能是NLP界出镜率最高的图 Transformer结构中&a…

最大公约数(欧几里得算法)

欧几里得算法 只需要记住一个公式&#xff08;不需要推导&#xff0c;这就是数论的基础知识&#xff09;&#xff1a; step1&#xff1a; 判断小括号内右边的数字 b 是否为0&#xff0c;如果为0&#xff0c;输出小括号左边的数字 a &#xff0c;就是一开始要求的两个数的最大…

深度学习入门笔记

深度学习入门笔记 感知机逻辑与门与非门或门多层感知机异或门 神经网络激活函数输出层设计损失函数均方误差 MSE交叉熵误差 反向传播算法计算图局部计算计算图反向传播反向传播 参数更新训练过程总结 该篇文章为本人学习笔记的一部分。笔记基于《深度学习入门 基于python理论实…

49-结构化程序设计方法的理解

‌结构化程序设计方法‌是一种以提高程序可读性、易维护性、可调性和可扩充性为目标的程序设计方法。它基于模块化设计原则&#xff0c;将程序划分为多个功能模块&#xff0c;每个模块负责实现特定的功能。这种方法强调使用三种基本控制结构&#xff1a;顺序、选择和循环&#…

在Linux下搭建go环境

下载go go官网&#xff1a;All releases - The Go Programming Language 我们可以吧压缩包下载到Windows上再传到Linux上&#xff0c;也可以直接web下载&#xff1a; wget https://golang.google.cn/dl/go1.23.0.linux-amd64.tar.gz 解压 使用命令解压&#xff1a; tar -x…

关于前端布局的基础知识

float 横向布局 float 实现横向布局&#xff0c;需要向横着布局的元素添加float 其值left right 存在问题 如果使用float 所在父级五高度&#xff0c;会导致下方的元素上移 top的高度被吞了 解决方法&#xff1a; 给父级元素设置高度&#xff1a;不推荐&#xff0c;需要给父级…

专题◉万字长文!盘点过去一年最出圈的Prompt项目教程,有3份在悄悄更新

1. OpenAI 官方出品 | 提示工程最权威的教程 (最新版) 2023年6月&#xff0c;OpenAI 发布了一篇〖*GPT Best Practice (GPT 最佳实践)* 〗教程&#xff0c;详细介绍 ChatGPT Prompt 交互策略&技巧&#xff0c;并且给出了示例说明。 一年时间过去了&#xff0c;OpenAI 不…