JavaScript AJAX 实现,演示如何将 Token 添加到 Authorization

以下是一个完整的原生 JavaScript AJAX 实现,演示如何将 Token 添加到 Authorization 头部的示例:

基础实现

html复制代码

<!DOCTYPE html>
<html>
<head><title>AJAX Token 示例</title><script>// 获取当前用户的 Token(实际应用中从安全存储获取)function getAuthToken() {// 实际项目中应从 localStorage/cookie 获取return "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";}// 发送带 Token 的 AJAX 请求function fetchDataWithToken() {const xhr = new XMLHttpRequest();const url = 'https://api.example.com/protected-data';const token = getAuthToken();// 配置请求xhr.open('GET', url, true);// 设置 Authorization 头部xhr.setRequestHeader('Authorization', `Bearer ${token}`);xhr.setRequestHeader('Content-Type', 'application/json');// 处理响应xhr.onreadystatechange = function() {if (xhr.readyState === XMLHttpRequest.DONE) {const status = xhr.status;if (status >= 200 && status < 300) {console.log('响应数据:', JSON.parse(xhr.responseText));document.getElementById('result').innerText = `请求成功: ${xhr.responseText}`;} else {console.error('请求失败:', xhr.statusText);document.getElementById('result').innerText = `错误 ${xhr.status}: ${xhr.statusText}`;}}};// 错误处理xhr.onerror = function() {console.error('网络错误');document.getElementById('result').innerText = '网络请求失败';};// 发送请求xhr.send();}</script>
</head>
<body><h1>AJAX Token 示例</h1><button onclick="fetchDataWithToken()">获取受保护数据</button><div id="result" style="margin-top: 20px;"></div>
</body>
</html>

封装为可重用模块

javascript复制代码

// ajaxWithAuth.jsconst API_BASE_URL = 'https://api.example.com';export default {/*** 发送带认证的 AJAX 请求* @param {string} method - HTTP 方法 (GET, POST, PUT, DELETE)* @param {string} endpoint - API 端点* @param {object} [data] - 请求数据* @returns {Promise} 返回 Promise*/request(method, endpoint, data = null) {return new Promise((resolve, reject) => {const xhr = new XMLHttpRequest();const url = `${API_BASE_URL}${endpoint}`;const token = this.getAuthToken();xhr.open(method, url, true);// 设置头部xhr.setRequestHeader('Authorization', `Bearer ${token}`);xhr.setRequestHeader('Content-Type', 'application/json');xhr.onload = function() {if (xhr.status >= 200 && xhr.status < 300) {try {resolve(JSON.parse(xhr.responseText));} catch (e) {resolve(xhr.responseText);}} else {reject({status: xhr.status,statusText: xhr.statusText});}};xhr.onerror = function() {reject({status: 0,statusText: '网络错误'});};xhr.send(data ? JSON.stringify(data) : null);});},// 获取认证 TokengetAuthToken() {// 实际实现从安全存储获取return localStorage.getItem('authToken') || sessionStorage.getItem('authToken') || '';},// 封装常用方法get(endpoint) {return this.request('GET', endpoint);},post(endpoint, data) {return this.request('POST', endpoint, data);},put(endpoint, data) {return this.request('PUT', endpoint, data);},delete(endpoint) {return this.request('DELETE', endpoint);}
};

使用示例

html复制代码

<script type="module">import ajax from './ajaxWithAuth.js';// 登录示例async function login() {try {const response = await ajax.post('/login', {username: 'user@example.com',password: 'securePassword123'});// 保存 token 到本地存储localStorage.setItem('authToken', response.token);console.log('登录成功');} catch (error) {console.error('登录失败:', error);}}// 获取受保护数据async function fetchProtectedData() {try {const userData = await ajax.get('/user/profile');console.log('用户数据:', userData);const orders = await ajax.get('/user/orders');console.log('订单数据:', orders);} catch (error) {console.error('请求失败:', error);// 处理 Token 过期if (error.status === 401) {console.log('Token过期,尝试刷新...');await refreshToken();return fetchProtectedData(); // 重试请求}}}// Token 刷新逻辑async function refreshToken() {try {const refreshToken = localStorage.getItem('refreshToken');const response = await ajax.post('/auth/refresh', { refreshToken });localStorage.setItem('authToken', response.accessToken);console.log('Token刷新成功');} catch (error) {console.error('刷新Token失败:', error);logout(); // 刷新失败则登出}}// 登出逻辑function logout() {localStorage.removeItem('authToken');localStorage.removeItem('refreshToken');console.log('用户已登出');}// 初始化document.addEventListener('DOMContentLoaded', () => {if (localStorage.getItem('authToken')) {fetchProtectedData();} else {document.getElementById('login-section').style.display = 'block';}});
</script>

安全增强措施

javascript复制代码

// 安全增强版
const ajaxSecure = {// ... 基础代码同上 ...request(method, endpoint, data = null) {return new Promise((resolve, reject) => {// ... 同上 ...// 添加安全头部xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');xhr.setRequestHeader('X-CSRF-Protection', this.getCSRFToken());// 添加请求时间戳防止缓存const timestamp = new Date().getTime();const finalUrl = endpoint.includes('?') ? `${url}&_t=${timestamp}` : `${url}?_t=${timestamp}`;xhr.open(method, finalUrl, true);// ... 其余代码 ...});},// 获取 CSRF TokengetCSRFToken() {const cookieValue = document.cookie.split('; ').find(row => row.startsWith('XSRF-TOKEN='))?.split('=')[1];return cookieValue || '';},// 自动处理 Token 刷新async requestWithRefresh(method, endpoint, data) {try {return await this.request(method, endpoint, data);} catch (error) {if (error.status === 401 && !endpoint.includes('/auth/refresh')) {await this.refreshToken();return this.request(method, endpoint, data);}throw error;}},// 刷新 Tokenasync refreshToken() {const refreshToken = localStorage.getItem('refreshToken');if (!refreshToken) throw new Error('无可用刷新令牌');try {const response = await this.request('POST', '/auth/refresh', {refreshToken});this.saveTokens(response);return true;} catch (error) {this.clearTokens();throw error;}},// 安全保存 TokensaveTokens(authData) {// 使用安全存储方式localStorage.setItem('authToken', authData.accessToken);// 刷新令牌使用 HTTP Only Cookie 存储(由服务器设置)document.cookie = `refreshToken=${authData.refreshToken}; Secure; HttpOnly; SameSite=Strict; path=/`;},// 清除 TokenclearTokens() {localStorage.removeItem('authToken');document.cookie = 'refreshToken=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';}
};

完整流程图

mermaid复制代码导出svg

最佳实践建议

  1. Token 存储安全

    javascript复制代码

    // 使用加密存储(浏览器扩展)
    async function secureSetItem(key, value) {if (window.crypto && window.crypto.subtle) {const encrypted = await encryptData(value);localStorage.setItem(key, encrypted);} else {// 回退方案:会话存储 + Base64sessionStorage.setItem(key, btoa(unescape(encodeURIComponent(value))));}
    }
    
  2. 添加请求签名

    javascript复制代码

    function signRequest(method, url, body) {const timestamp = Date.now();const nonce = Math.random().toString(36).substring(2, 12);const dataToSign = `${method}|${url}|${timestamp}|${nonce}|${body ? JSON.stringify(body) : ''}`;const hmac = CryptoJS.HmacSHA256(dataToSign, SECRET_KEY);return {'X-Signature': hmac.toString(CryptoJS.enc.Base64),'X-Timestamp': timestamp,'X-Nonce': nonce};
    }
    
  3. 双重 Token 验证

    javascript复制代码

    function setAuthHeaders(xhr) {const token = getAuthToken();xhr.setRequestHeader('Authorization', `Bearer ${token}`);// 添加设备指纹验证const deviceId = generateDeviceId();xhr.setRequestHeader('X-Device-ID', deviceId);
    }function generateDeviceId() {// 基于浏览器指纹生成唯一IDconst canvas = document.createElement('canvas');const ctx = canvas.getContext('2d');ctx.fillText('ID', 10, 10);return canvas.toDataURL().hashCode();
    }
    

这个实现展示了如何在原生 AJAX 请求中添加认证 Token,并提供了企业级的安全增强措施。实际项目中,建议结合具体框架使用更高级的 HTTP 客户端(如 Axios),但理解底层原理对于处理特殊场景非常重要。

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

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

相关文章

开发语言的优劣势对比及主要应用领域分析

开发语言是程序员用来编写软件指令的工具。每种语言都有自己的设计哲学、语法&#xff08;规则&#xff09;和应用场景&#xff0c;但没有“放之四海而皆准”的最佳语言。以下是主流和重要开发语言的介绍&#xff0c;按主要应用领域分类&#xff1a; 一、全能型语言 (可在多个领…

Java学习-------事务失效

在 Java 开发中&#xff0c;事务是保证数据一致性和完整性的关键机制&#xff0c;尤其在涉及多步数据库操作的业务场景中不可或缺。然而&#xff0c;在实际开发过程中&#xff0c;事务常常会出现 “失效” 的情况 —— 预期的回滚没有发生&#xff0c;数据出现不一致。 Java 事…

JavaScript 01 JavaScript 是什么

1.1 JavaScript 是什么JavaScript 是一门世界上最流行的脚本语言&#xff08;基本所有平台的所有软件都会用到它&#xff09;。“1994年&#xff0c;网景公司(Netscape)发布了Navigator浏览器0.9版。这是历史上第一个比较成熟的网络浏览器&#xff0c;轰动一时。但是&#xff0…

Bun v1.2.19发布,node_modules隔离,sql比node快6倍

大家好,我是农村程序员,独立开发者,行业观察员,前端之虎陈随易。我会在这里分享关于 独立开发、编程技术、思考感悟 等内容,欢迎关注。 技术群与交朋友请在个人网站联系我,网站 1️⃣:https://chensuiyi.me,网站 2️⃣:https://me.yicode.tech。 如果你觉得本文有用…

【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 主页布局实现

大家好&#xff0c;我是java1234_小锋老师&#xff0c;最近写了一套【NLP舆情分析】基于python微博舆情分析可视化系统(flaskpandasecharts)视频教程&#xff0c;持续更新中&#xff0c;计划月底更新完&#xff0c;感谢支持。今天讲解主页布局实现 视频在线地址&#xff1a; …

# 微调需要准备哪些环境配置?

微调需要准备哪些环境配置&#xff1f; 如果没有 GPU&#xff0c;即便是微调较小的大语言模型&#xff08;LLMs&#xff09;&#xff0c;过程也会比较慢。如果你已经有了现成的 GPU&#xff0c;那就可以直接开工了。不过&#xff0c;并不是所有人都能负担得起 GPU—— 这种情况…

ClickHouse物化视图避坑指南:原理、数据迁移与优化

摘要ClickHouse物化视图通过预计算和自动更新机制&#xff0c;显著提升大数据分析查询性能&#xff0c;尤其适合高并发聚合场景。本文将深入解析其技术原理、生产实践中的优化策略&#xff0c;以及数据迁移的实战经验。一、物化视图核心概念ClickHouse的物化视图(Materialized …

Springboot3整合Elasticsearch8(elasticsearch-java)

1、Elasticsearch的JAVA客户端选择 Elasticsearch官方支持的客户端 客户端名称简介使用建议Elasticsearch Java API Client&#xff08;新客户端&#xff09;官方推荐的新客户端&#xff0c;基于 JSON Mapping&#xff08;如 ElasticsearchClient 类&#xff09;&#xff0c;…

OpenCV 官翻8 - 其他算法

文章目录高动态范围成像引言曝光序列源代码示例图像说明结果色调映射图像曝光融合附加资源高级图像拼接 API&#xff08;Stitcher 类&#xff09;目标代码说明相机模型试用指南图像拼接详解 (Python OpenCV >4.0.1)stitching_detailed如何使用背景减除方法目标代码代码解析结…

2025年一区SCI-回旋镖气动椭圆优化算法Boomerang Aerodynamic Ellipse-附Matlab免费代码

引言 本期介绍一种新的元启发式算法——回旋镖气动椭圆优化算法Boomerang Aerodynamic Ellipse Optimizer (BAEO)。该优化器的灵感来自于飞行中的回旋镖的空气动力学行为&#xff0c;明确地建模了释放角和发射力如何塑造其轨迹。于2025年7月最新发表在JCR 1区&#xff0c;中科…

Custom SRP - Custom Render Pipeline

https://catlikecoding.com/unity/tutorials/custom-srp/custom-render-pipeline/ 1. 新建 Render Pipeline 任何内容的渲染&#xff0c;最终都是要由 unity 决定在哪里&#xff0c;什么时候&#xff0c;以哪些参数进行渲染。根据目标效果的复杂程度&#xff0c;决定渲染的过程…

C语言面向对象编程

1.内核通用链表一、什么是 list_head&#xff1f;list_head 是 Linux 内核中自己实现的一种 双向循环链表 的结构&#xff0c;定义在 <linux/list.h> 中。它设计得非常轻巧、灵活&#xff0c;广泛用于内核模块、驱动、进程调度、网络协议栈等。它的关键思想是&#xff1a…

Spring Boot+Redis Zset:三步构建高可靠延迟队列系统

系统设计架构图---------------- ----------------- ---------------- | | | | | | | 生产者 |------>| Redis ZSet |------>| 定时任务消费者 | | (添加延迟任务) | | (延…

MCP vs 传统集成方案:REST API、GraphQL、gRPC的终极对比

MCP vs 传统集成方案&#xff1a;REST API、GraphQL、gRPC的终极对比 &#x1f31f; Hello&#xff0c;我是摘星&#xff01; &#x1f308; 在彩虹般绚烂的技术栈中&#xff0c;我是那个永不停歇的色彩收集者。 &#x1f98b; 每一个优化都是我培育的花朵&#xff0c;每一个特…

SQL语句中锁的使用与优化

一、锁机制简介1.定义在数据库中&#xff0c;除了传统的计算资源&#xff08;如CPU、RAM、I/O等&#xff09;的争用以外&#xff0c;数据也是一种供需要用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题&#xff0c;锁冲突也是影响数据库并…

Linux笔记1——简介安装

操作系统给用户一个操作界面&#xff0c;用户通过操作界面使用系统资源Linux内核管理控制硬件&#xff0c;和硬件打交道SCSI&#xff08;盘&#xff09;sd**;第一个*表示磁盘顺序&#xff0c;第二个*表示分区。例如&#xff1a;sda\sdb\sdc,sda1,sda2NVMe&#xff08;盘&#x…

GoLand 部署第一个项目

前言&#xff1a;Go环境部署分为两种模式&#xff0c;一种是基于GOPATH部署&#xff08;老版本&#xff09;&#xff0c;另一种是基于Module部署&#xff08;新版本v1.11开始&#xff09;。GOPATH&#xff1a;需要配置GOPATH路径&#xff0c;将GOPATH目录视为工作目录&#xff…

Mosaic数据增强介绍

1. 核心概念与目标Mosaic 是一种在计算机视觉&#xff08;尤其是目标检测任务&#xff09;中非常流行且强大的数据增强技术。它最早由 Ultralytics 的 Alexey Bochkovskiy 在 YOLOv4 中提出并推广&#xff0c;后来被广泛应用于 YOLOv5, YOLOv7, YOLOv8 等模型以及其他目标检测框…

LINUX 722 逻辑卷快照

逻辑卷快照 lvcreate -L 128M -s -n lv1-snap /dev/vg1/lv1 lvs lvscan mount -o ro /dev/vg1/lv1 /mmt/lv1-snap dmsetup ls --tree 测试 lvs /dev/vg1/lv1-snap dd if/dev/zero of/uc1/test bs1M count40 lvs /dev/vg1/lv1-snap 问题 [rootweb ~]# cd /mnt [rootweb mnt]# m…

Springboot+vue个人健康管理系统的设计与实现

文章目录前言详细视频演示具体实现截图后端框架SpringBoot前端框架Vue持久层框架MyBaits成功系统案例&#xff1a;代码参考数据库源码获取前言 博主介绍:CSDN特邀作者、985高校计算机专业毕业、现任某互联网大厂高级全栈开发工程师、Gitee/掘金/华为云/阿里云/GitHub等平台持续…