使用Express的sendFile时,如何将Token传递给客户端供后续请求复用?
解决方案:在Express中传递Bearer Token给客户端
嘿,这个需求其实挺常见的,我来给你捋几个靠谱的实现方式,都是我在实际项目里验证过的:
方法1:用模板引擎动态注入Token(最直接)
你现在用sendFile返回静态HTML,没法动态修改内容,所以可以换成模板引擎(比如EJS、Pug)来渲染页面,把Token直接嵌入到前端JS里。
步骤:
- 安装模板引擎(以EJS为例):
npm install ejs
- 配置Express使用模板引擎:
const express = require('express'); const app = express(); // 设置模板引擎为EJS app.set('view engine', 'ejs'); // 设置模板文件所在目录(默认是views文件夹) app.set('views', './views');
- 把你的静态HTML文件改成
.ejs模板,在合适的位置注入Token:
<!-- views/index.ejs --> <!DOCTYPE html> <html> <head> <title>My App</title> </head> <body> <script> // 从模板变量获取Token,并存到localStorage方便后续Axios使用 const authToken = '<%= authToken %>'; if (authToken) { localStorage.setItem('apiAuthToken', authToken); } // 后续Axios请求时自动带上Token axios.interceptors.request.use(config => { const token = localStorage.getItem('apiAuthToken'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); </script> </body> </html>
- 修改路由,从请求头提取Token并渲染模板:
app.get('/', (req, res) => { // 从Authorization头提取Bearer Token(注意去掉"Bearer "前缀) const bearerToken = req.headers.authorization?.split(' ')[1]; // 渲染模板并传递Token变量 res.render('index', { authToken: bearerToken }); });
方法2:通过Cookie传递Token(适合跨页面共享)
如果希望Token在多个页面间共享,或者需要更规范的持久化存储,可以用Cookie传递(注意如果前端需要直接访问Token,不能设置HttpOnly属性):
后端代码:
const path = require('path'); app.get('/', (req, res) => { const bearerToken = req.headers.authorization?.split(' ')[1]; if (bearerToken) { // 设置Cookie,生产环境记得开启secure和sameSite属性 res.cookie('apiAuthToken', bearerToken, { httpOnly: false, // 必须设为false,否则前端JS无法读取 secure: process.env.NODE_ENV === 'production', // 生产环境强制HTTPS传输 sameSite: 'strict', // 防范CSRF攻击 maxAge: 24 * 60 * 60 * 1000 // 过期时间设为1天 }); } // 继续返回你的静态HTML文件 res.sendFile(path.join(__dirname, 'public', 'index.html')); });
前端代码:
// 从Cookie中提取Token的工具函数 function getCookie(name) { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) return parts.pop().split(';').shift(); } // 提取Token并配置Axios const authToken = getCookie('apiAuthToken'); if (authToken) { axios.defaults.headers.common.Authorization = `Bearer ${authToken}`; }
方法3:通过自定义响应头传递(无侵入式)
如果不想修改HTML结构或引入模板引擎,还可以通过自定义响应头把Token传给前端,然后前端在页面加载时主动获取:
后端代码:
const path = require('path'); app.get('/', (req, res) => { const bearerToken = req.headers.authorization?.split(' ')[1]; if (bearerToken) { // 设置自定义响应头 res.set('X-Auth-Token', bearerToken); } res.sendFile(path.join(__dirname, 'public', 'index.html')); });
前端代码:
// 页面加载完成后,发送HEAD请求获取响应头 window.addEventListener('load', async () => { try { const response = await fetch(window.location.href, { method: 'HEAD' }); const authToken = response.headers.get('X-Auth-Token'); if (authToken) { localStorage.setItem('apiAuthToken', authToken); // 配置Axios自动携带Token axios.defaults.headers.common.Authorization = `Bearer ${authToken}`; } } catch (err) { console.error('获取认证Token失败:', err); } });
安全提示
- 生产环境必须启用HTTPS:防止Token在传输过程中被窃听
- 不要将Token直接暴露在全局变量中,优先存储到
localStorage或sessionStorage - 使用Cookie时,
secure属性一定要在生产环境开启,确保仅通过HTTPS传输 - 给Token设置合理的过期时间,避免长期有效带来的安全风险
内容的提问来源于stack exchange,提问作者Darren
相关产品推荐
相关产品推荐

