安全问题
CSRF Token(仿伪造令牌)
写进 Headers.Authorization
过程
- 用户登录后,登录接口生成Token
- 用户接收到Token后,存储起来,每次请求都带上Token以验证身份
Token应该存储在哪里
1.LocalStorage
优点:
- 容量较大,通常可以存储 5MB 以上的数据。
- 存取速度快,操作简单。
缺点:
- 存放在浏览器端,容易受到 XSS(跨站脚本攻击) 的影响,黑客如果能够在你的页面中执行 JavaScript,就能读取 localStorage 中的内容。
- localStorage 只会在浏览器端存储,不会随请求一起发送,因此需要手动将其包含在请求中。
如何防止XSS攻击?—— CSP(Content Security Policy)
通过 HTTP 响应头(Content-Security-Policy)或 HTML
<meta>
标签,向浏览器传达允许加载的资源类型、来源、执行脚本的限制等规则
- 通过 HTTP 响应头设置 CSP:
app.use((req, res, next) => {
res.setHeader('Content-Security-Policy', "default-src 'self'; script-src 'self'; object-src 'none';");
next();
});
- 通过 HTML
<meta>
标签设置 CSP:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self';">
- 属性解析:
- default-src:定义默认的资源加载源,用于那些没有单独设置的类型。
- script-src:控制哪些源(域名、协议等)可以加载脚本
- script-src-elem 'none'; 禁止通过 script 标签加载外部脚本
- script-src-attr 'none'; 禁止内联事件处理程序(如
<div onclick="...">
)
- style-src:控制哪些源可以加载样式表
- style-src-elem 'none'; 禁止通过 style 标签加载外部样式
- style-src-attr 'none'; 禁止内联样式
- img-src:控制哪些源可以加载图像。
- object-src:控制哪些源可以加载插件或对象(例如Flash插件)。
- font-src:指定允许加载字体的源。
- connect-src:控制可以通过 XMLHttpRequest、WebSocket 等方式进行连接的源。
- child-src:指定允许加载子资源的源,包括
<iframe>
、<frame>
和<object>
标签。 - frame-ancestors:是否允许页面被嵌套在其他站点的 iframe 中
- 属性值
- 'self':只允许加载来自相同源的资源。
- 指定域名
- 'none':禁止
- 'unsafe-inline':允许内联脚本和样式,但这会降低安全性,建议尽量避免使用。
- 'unsafe-eval':允许使用 eval() 等危险的 JavaScript 特性。使用此选项可能会使你的站点容易受到攻击,尽量避免。
- nonce-
<base64-value>
:使用 nonce 来标识特定的内联脚本,使其可以执行。 - sha256-
<hash>
:使用哈希值来标识特定的内联脚本,从而允许执行。
Content-Security-Policy: default-src 'self';
// 允许加载指定的外部脚本
Content-Security-Policy: default-src 'self'; script-src 'self' https://apis.google.com;
// 防止内联脚本和 eval():
Content-Security-Policy: script-src 'self'; object-src 'none'; style-src 'self';
// 允许指定的内联脚本(但需要 nonce 或 hash)
Content-Security-Policy: script-src 'self' 'nonce-XYZ123';
<script nonce="XYZ123">
console.log('This is a safe inline script');
</script>
/*防止你的页面被嵌套在其他站点的 iframe 中*/
Content-Security-Policy: default-src 'self'; frame-ancestors 'none';
2.Cookie
优点:
- cookie 会自动随每次 HTTP 请求发送到服务器,不需要手动操作。
- 可以设置 HttpOnly 和 Secure 标志,增强安全性。HttpOnly 防止 JavaScript 访问(HttpOnly是cookie的属性) ,Secure 确保只有在 HTTPS 请求中传输。
缺点:
- cookie 有大小限制(一般为 4KB)。(不过就放一个Token也够用了)
- cookie 会随着每次请求一起发送,增加了网络负担,尤其是对于每次请求都需要携带 token 的情况下。
HttpOnly设置防止Javascript访问
// 使用 Node.js 和 Express 设置 cookie
res.cookie('AccessToken', 'your-token-here', {
httpOnly: true, // 防止 JavaScript 访问
secure: true, // 只有在 HTTPS 下才会发送
maxAge: 1000 * 60 * 60 * 24, // 可选:设置 cookie 过期时间
sameSite: 'Strict', // 防止 CSRF 攻击
});
总结
如果不需要考虑在其他页面使用
iframe
内嵌的情况,可以使用localStorage
+CSP
使用Javascript
脚本访问localStorage(XSS
攻击);如果要考虑允许在其他页面内嵌
iframe
,建议使用cookie
+HttpOnly
- 缺点:写到cookie里,每次请求都会加上,增加网络负担
- HttpOnly只是限制 Javascript 访问 cookie,无法限制 Javascript 脚本其他的代码执行;