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

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

基础实现

html复制代码




  AJAX Token 示例
  


  

AJAX Token 示例

封装为可重用模块

javascript复制代码

// ajaxWithAuth.js

const 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);
    });
  },
  
  // 获取认证 Token
  getAuthToken() {
    // 实际实现从安全存储获取
    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复制代码


安全增强措施

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 Token
  getCSRFToken() {
    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;
    }
  },
  
  // 刷新 Token
  async 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;
    }
  },
  
  // 安全保存 Token
  saveTokens(authData) {
    // 使用安全存储方式
    localStorage.setItem('authToken', authData.accessToken);
    
    // 刷新令牌使用 HTTP Only Cookie 存储(由服务器设置)
    document.cookie = `refreshToken=${authData.refreshToken}; Secure; HttpOnly; SameSite=Strict; path=/`;
  },
  
  // 清除 Token
  clearTokens() {
    localStorage.removeItem('authToken');
    document.cookie = 'refreshToken=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
  }
};

完整流程图

mermaid复制代码导出svg

JavaScript AJAX 实现,演示如何将 Token 添加到 Authorization_第1张图片

最佳实践建议

  1. Token 存储安全

    javascript复制代码

    // 使用加密存储(浏览器扩展)
    async function secureSetItem(key, value) {
      if (window.crypto && window.crypto.subtle) {
        const encrypted = await encryptData(value);
        localStorage.setItem(key, encrypted);
      } else {
        // 回退方案:会话存储 + Base64
        sessionStorage.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() {
      // 基于浏览器指纹生成唯一ID
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      ctx.fillText('ID', 10, 10);
      return canvas.toDataURL().hashCode();
    }
    

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

你可能感兴趣的:(javascript,ajax,okhttp)