Token与axios拦截器

目录

一、Token 详解

1. Token 的定义与作用

2. Token 的工作流程

3. Token 的优势

4. Token 的安全实践

5. JWT 结构示例

二、Axios 拦截器详解

1. 拦截器的作用

2. 请求拦截器

3. 响应拦截器

4. 拦截器常见场景

5. 移除拦截器

三、完整代码示例

四、总结

五、axios高级配置

1. 全局默认配置

2. 创建实例(隔离配置)

3. 取消请求

4. 并发请求

5. 文件上传

6. 文件下载

六、XSS(跨站脚本攻击)

1. 攻击原理

2. 攻击示例

3. 防御措施

七、CSRF(跨站请求伪造)

1. 攻击原理

2. 防御措施

八、Token 在防御中的应用

1. Token 类型

2. 安全实践

3. JWT 安全增强

九、总结


一、Token 详解

1. Token 的定义与作用

Token(令牌)是用于在客户端和服务器之间安全传递用户身份信息的一种凭证,通常用于身份验证和授权流程。

  • 核心作用

    • 身份验证(Authentication):验证用户身份(如登录状态)。

    • 授权(Authorization):授予用户访问特定资源的权限(如 API 端点)。

  • 常见类型

    • JWT(JSON Web Token):最流行的无状态令牌格式,包含头部、载荷和签名。

    • OAuth2 Token:用于第三方授权(如使用 Google 登录)。

    • Session Token:传统有状态会话标识(如 Session ID)。


2. Token 的工作流程
1. 用户登录 → 服务器验证凭据 → 生成 Token → 返回给客户端
2. 客户端存储 Token(如 localStorage、Cookie)
3. 客户端发起请求时携带 Token(通常通过 HTTP 头)
4. 服务器验证 Token → 授权访问资源

3. Token 的优势
  • 无状态性:服务器无需存储会话信息(适合分布式系统)。

  • 跨域支持:易于在多个服务间传递用户身份(如微服务架构)。

  • 安全性:可通过签名(JWT)或加密防止篡改。


4. Token 的安全实践
  • 存储方式

    • 推荐:使用 httpOnlySecureSameSite=Strict 的 Cookie(防 XSS)。

    • 次选localStorage 或 sessionStorage(需防范 XSS)。

  • 传输方式

    • 通过 Authorization 请求头传输(如 Bearer <token>)。

  • 过期时间

    • 设置短期有效的 Token(如 15 分钟),配合 Refresh Token 续期。


5. JWT 结构示例
Header:  {"alg": "HS256", "typ": "JWT"}
Payload: {"sub": "user123", "exp": 1620000000}
Signature: HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

二、Axios 拦截器详解

1. 拦截器的作用

拦截器允许在请求发送前或响应返回后,统一添加逻辑(如添加 Token、处理错误)。

2. 请求拦截器
axios.interceptors.request.use(
  config => {
    // 请求发送前的处理(如添加 Token)
    const token = localStorage.getItem('token');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  error => {
    // 请求错误处理
    return Promise.reject(error);
  }
);
3. 响应拦截器
axios.interceptors.response.use(
  response => {
    // 响应成功处理(状态码 2xx)
    return response.data; // 直接返回数据,简化后续处理
  },
  async error => {
    // 响应错误处理(状态码非 2xx 或网络错误)
    const originalRequest = error.config;
    
    // Token 过期且未重试过 → 尝试刷新 Token
    if (error.response?.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;
      try {
        const newToken = await refreshToken(); // 刷新 Token
        localStorage.setItem('token', newToken);
        originalRequest.headers.Authorization = `Bearer ${newToken}`;
        return axios(originalRequest); // 重试原请求
      } catch (refreshError) {
        logout(); // 刷新失败 → 跳转登录页
        return Promise.reject(refreshError);
      }
    }
    
    // 其他错误统一处理
    return Promise.reject(error);
  }
);

4. 拦截器常见场景
  • 自动添加 Token:统一为所有请求添加 Authorization 头。

  • Token 过期自动刷新:401 错误时刷新 Token 并重试请求。

  • 统一错误处理:网络错误、服务器错误等全局捕获。

  • 加载状态管理:显示/隐藏全局加载动画。


5. 移除拦截器
const requestInterceptor = axios.interceptors.request.use(...);
const responseInterceptor = axios.interceptors.response.use(...);

// 移除拦截器
axios.interceptors.request.eject(requestInterceptor);
axios.interceptors.response.eject(responseInterceptor);

三、完整代码示例

1. Token 管理 + Axios 拦截器

// 封装 Axios 实例
const api = axios.create({
  baseURL: 'https://api.example.com',
});

// 请求拦截器:添加 Token
api.interceptors.request.use(
  config => {
    const token = localStorage.getItem('token');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  error => Promise.reject(error)
);

// 响应拦截器:处理 Token 过期
api.interceptors.response.use(
  response => response.data,
  async error => {
    const originalRequest = error.config;
    
    // Token 过期且未重试过
    if (error.response?.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;
      try {
        const newToken = await refreshToken();
        localStorage.setItem('token', newToken);
        originalRequest.headers.Authorization = `Bearer ${newToken}`;
        return api(originalRequest);
      } catch (refreshError) {
        logout();
        return Promise.reject(refreshError);
      }
    }
    
    // 其他错误处理
    return Promise.reject(error);
  }
);

// 刷新 Token 的函数
async function refreshToken() {
  const refreshToken = localStorage.getItem('refreshToken');
  const response = await axios.post('/auth/refresh', { refreshToken });
  return response.data.token;
}

// 退出登录
function logout() {
  localStorage.removeItem('token');
  localStorage.removeItem('refreshToken');
  window.location.href = '/login';
}

四、总结

  • Token:身份验证与授权的核心凭证,需安全存储和传输。

  • Axios 拦截器:实现全局请求/响应逻辑(如 Token 管理、错误处理),提升代码复用性和可维护性。

  • 最佳实践

    • 使用 httpOnly Cookie 存储 Token(防 XSS)。

    • 短期 Token + Refresh Token 提升安全性。

    • 拦截器中处理 Token 刷新避免并发问题。


五、axios高级配置

1. 全局默认配置
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = 'Bearer token123';
axios.defaults.timeout = 5000; // 超时时间(毫秒)
2. 创建实例(隔离配置)
const api = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 3000
});

api.get('/data'); // 使用实例发送请求
3. 取消请求

使用 CancelToken(旧版):

const source = axios.CancelToken.source();

axios.get('/data', {
  cancelToken: source.token
}).catch(error => {
  if (axios.isCancel(error)) {
    console.log('请求被取消:', error.message);
  }
});

// 取消请求
source.cancel('用户手动取消');

使用 AbortController(新版,推荐):

const controller = new AbortController();

axios.get('/data', {
  signal: controller.signal
}).catch(error => {
  if (error.name === 'CanceledError') {
    console.log('请求已取消');
  }
});

// 取消请求
controller.abort();
4. 并发请求
const request1 = axios.get('/data1');
const request2 = axios.get('/data2');

axios.all([request1, request2])
  .then(axios.spread((res1, res2) => {
    console.log(res1.data, res2.data);
  }));
5. 文件上传
const formData = new FormData();
formData.append('file', fileInput.files[0]);

axios.post('/upload', formData, {
  headers: { 'Content-Type': 'multipart/form-data' }
});
6. 文件下载
axios.get('/download', {
  responseType: 'blob' // 指定响应类型为二进制流
}).then(response => {
  const url = window.URL.createObjectURL(new Blob([response.data]));
  const link = document.createElement('a');
  link.href = url;
  link.setAttribute('download', 'file.pdf');
  document.body.appendChild(link);
  link.click();
});

六、XSS(跨站脚本攻击)

1. 攻击原理
  • 定义:攻击者向网页注入恶意脚本(JavaScript、HTML、CSS),当其他用户访问该页面时,脚本在用户浏览器执行,窃取数据或劫持会话。

  • 类型

    • 存储型 XSS:恶意脚本永久存储在目标服务器(如论坛评论)。

    • 反射型 XSS:恶意脚本通过 URL 参数反射到页面(如钓鱼链接)。

    • DOM 型 XSS:前端 JavaScript 动态修改 DOM 时触发漏洞。

2. 攻击示例
// 用户输入未过滤,直接渲染到页面
用户评论内容:<script>stealCookie()</script>
3. 防御措施
  • 输入过滤与转义

    • 对用户输入的内容进行 HTML 转义(如 < → &lt;)。

    • 使用安全的库(如 DOMPurify)清理 HTML。

  • Content Security Policy(CSP)

    Content-Security-Policy: default-src 'self'; script-src 'self' trusted.com
    • 限制页面只能加载指定来源的脚本、样式等资源。

  • 设置 HttpOnly Cookie

    • 防止 JavaScript 通过 document.cookie 读取敏感 Cookie。

    // 服务器设置 Cookie
    Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Strict

七、CSRF(跨站请求伪造)

1. 攻击原理
  • 定义:攻击者诱导用户访问恶意页面,该页面自动向目标网站发起请求(利用用户已登录的 Cookie)。

  • 示例

    <!-- 恶意页面中的图片标签 -->
    <img src="https://bank.com/transfer?to=attacker&amount=1000">
2. 防御措施
  • CSRF Token

    • 服务器生成随机 Token 嵌入表单或请求头,验证请求的合法性。

    <form action="/transfer" method="POST">
      <input type="hidden" name="csrf_token" value="随机值">
    </form>
  • SameSite Cookie

    • 限制 Cookie 仅在相同站点请求中发送。

    Set-Cookie: sessionId=abc123; SameSite=Strict; Secure
    • Strict:完全禁止第三方 Cookie。

    • Lax:允许安全导航(如链接跳转)携带 Cookie。

    • None:允许所有请求携带 Cookie(需配合 Secure)。

  • 验证请求来源

    • 检查 Origin 或 Referer 头部是否来自合法域名。


八、Token 在防御中的应用

1. Token 类型
  • CSRF Token:防御 CSRF 攻击,确保请求来自合法页面。

  • JWT(JSON Web Token):用于无状态身份验证,包含签名防篡改。

2. 安全实践
  • 存储方式

    • CSRF Token:存储在服务器 Session 或加密 Cookie 中。

    • JWT:通过 httpOnly + Secure Cookie 存储,或前端存储但结合短期有效期。

  • 传输方式

    • CSRF Token:嵌入表单隐藏字段或请求头(如 X-CSRF-Token)。

    • JWT:通过 Authorization: Bearer <token> 请求头传输。

3. JWT 安全增强
  • 签名验证:使用强加密算法(如 HS256、RS256)。

  • 有效期控制:设置短期有效的 exp 字段,配合 Refresh Token 续期。

  • 黑名单机制:注销时使特定 Token 失效。


九、总结

  • XSS 防御核心:防止恶意脚本注入,隔离用户输入与代码执行。

  • CSRF 防御核心:确保请求来源合法,阻断伪造请求。

  • Token 安全:结合存储安全(HttpOnly)、传输安全(HTTPS)和有效期管理。

综合防御策略:

攻击类型防御措施
XSS输入过滤 + CSP + HttpOnly Cookie + 避免 innerHTML 直接渲染用户输入。
CSRFCSRF Token + SameSite Cookie + 验证请求来源。
Token 安全使用 HTTPS + 安全存储(HttpOnly Cookie) + 短期有效 + 签名验证。

无感刷新token是指在前端发起请求时,如果当前的token已过期,则自动刷新token,并重新发起请求,达到用户无感知的效果。在axios中,可以通过拦截器实现无感刷新token的功能。 在axios中,我们可以通过使用请求拦截器和响应拦截器来实现无感刷新token的逻辑。首先,我们可以在请求拦截器中判断当前的token是否已过期。如果token未过期,则直接返回请求对象,如果token已过期,则在请求拦截器中发起刷新token的请求。 在刷新token的请求中,我们可以使用当前过期的token去请求后端接口,然后根据后端返回的结果来判断是否成功刷新token。如果刷新token成功,则将新的token更新到请求头信息中,并重新发起之前的请求。 在响应拦截器中,我们可以判断后端返回的响应状态码。如果响应状态码为401,说明当前的token已过期,则调用刷新token的逻辑重新获取token,并再次发起请求。如果刷新token的请求失败,则说明用户的登录状态无效,可以跳转到登录页面重新登录。 通过以上的逻辑,我们可以实现无感刷新token的效果,用户不需要手动处理token过期的问题,从而提升用户体验。同时在后端也需要配合实现刷新token的逻辑,并提供相应的接口供前端调用。 无感刷新token的实现涉及到了前后端的配合,前端通过axios拦截器实现token的自动刷新,后端提供相关的接口。通过这种方式,可以有效解决token过期后需要重新登录的问题,提升应用的用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值