跳到主要内容

安全问题

CSRF Token(仿伪造令牌)

写进 Headers.Authorization

过程

  1. 用户登录后,登录接口生成Token
  2. 用户接收到Token后,存储起来,每次请求都带上Token以验证身份

Token应该存储在哪里

1.LocalStorage

优点:

  • 容量较大,通常可以存储 5MB 以上的数据。
  • 存取速度快,操作简单。

缺点:

  • 存放在浏览器端,容易受到 XSS(跨站脚本攻击) 的影响,黑客如果能够在你的页面中执行 JavaScript,就能读取 localStorage 中的内容。
  • localStorage 只会在浏览器端存储,不会随请求一起发送,因此需要手动将其包含在请求中。

如何防止XSS攻击?—— CSP(Content Security Policy)

通过 HTTP 响应头(Content-Security-Policy)或 HTML <meta> 标签,向浏览器传达允许加载的资源类型、来源、执行脚本的限制等规则

  1. 通过 HTTP 响应头设置 CSP:
app.use((req, res, next) => {
res.setHeader('Content-Security-Policy', "default-src 'self'; script-src 'self'; object-src 'none';");
next();
});
  1. 通过 HTML <meta> 标签设置 CSP:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self';">
  1. 属性解析:
  • 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 中
  1. 属性值
  • '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 攻击
});

总结

  1. 如果不需要考虑在其他页面使用iframe内嵌的情况,可以使用localStorage + CSP使用Javascript脚本访问localStorage(XSS攻击);

  2. 如果要考虑允许在其他页面内嵌iframe,建议使用cookie + HttpOnly

    • 缺点:写到cookie里,每次请求都会加上,增加网络负担
    • HttpOnly只是限制 Javascript 访问 cookie,无法限制 Javascript 脚本其他的代码执行;