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
英文地址,請注明出處:http://en.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等平臺持續…