解决connect-src限制的实战经验与安全策略分析

杏花 安全 阅读 1,876
赞 19 收藏
二维码
手机扫码查看
反馈

connect-src这玩意儿,真的挺重要

说实话,我最早接触Content Security Policy(CSP)的时候,完全没把connect-src当回事。直到后来项目上线,用户反馈说API请求全挂了,我才意识到这个指令有多关键。简单来说,connect-src就是用来控制哪些外部资源可以通过脚本发起网络请求的。

解决connect-src限制的实战经验与安全策略分析

我的建议是:只要是涉及到AJAX、WebSocket或者fetch()这些网络请求的地方,都得提前规划好connect-src。不然等出问题了再改,那可真是要命。

我的写法,亲测靠谱

经过几个项目的打磨,我现在用的这套配置算是比较稳定的:

// 在Express中设置CSP头
const helmet = require('helmet');
app.use(
  helmet.contentSecurityPolicy({
    directives: {
      connectSrc: [
        "'self'",
        "https://api.jztheme.com",
        "wss://ws.jztheme.com",
        "https://cdn.jsdelivr.net"
      ]
    }
  })
);

这里有几个关键点要说一下:

  • 首先是’self’,这是必须加的,表示允许同源请求
  • 然后是具体的API域名,比如上面的api.jztheme.com
  • WebSocket要用wss协议,千万别漏了
  • 第三方CDN地址也要单独列出来

这种写法的好处是既安全又灵活。记得有个项目因为第三方统计服务的域名没加进去,导致数据全丢了,老板差点把我开了。

这几种错误写法,别再踩坑了

这些年见过太多奇葩的写法,我自己也踩过不少坑。最常见的错误就是下面这几种:

// 错误示例1:过于宽松
connectSrc: ["*"]

// 错误示例2:漏掉必要项
connectSrc: ["https://api.jztheme.com"]

// 错误示例3:混淆协议
connectSrc: ["ws://ws.jztheme.com"]

第一种写法看似省事,但等于没做防护,谁都能访问你的接口。第二种忘了加’self’,结果页面上的同源请求全挂了。第三种更离谱,WebSocket生产环境必须用wss,不能用ws。

还有个特别隐蔽的坑,就是动态生成的URL。比如这样:

const apiUrl = ${protocol}://${host}/api;
fetch(apiUrl);

这种情况,你得确保所有可能的组合都在connect-src里声明了,否则就会报错。

实际项目中的坑

去年做过一个电商项目,支付模块就栽在connect-src上。当时对接微信支付,文档里写着:

wx.chooseWXPay({
  timestamp: '',
  nonceStr: '',
  package: '',
  signType: '',
  paySign: '',
  success: function (res) {}
});

看着挺简单对吧?结果调用时一直报跨域错误。折腾了半天才发现,微信支付SDK会发起额外的网络请求,需要在connect-src里加上:

connectSrc: [
  "'self'",
  "https://api.jztheme.com",
  "https://api.mch.weixin.qq.com"
]

类似的坑还有很多。像Google Analytics、Facebook Pixel这些第三方服务,都需要单独声明域名。有时候文档里不会明说,只能靠抓包来看它们到底访问了哪些地址。

还遇到过一个有意思的情况。有次为了调试方便,临时加了个:

connectSrc: ["'unsafe-inline'"]

结果被安全部门直接叫停。他们说这跟不设防没啥区别,最后还是老老实实一个个加白名单。

一些实用的小技巧

说几个我觉得挺好用的做法:

  • 开发环境可以用report-only模式,先收集违规报告,再调整规则
  • 不确定具体域名时,可以先用通配符测试,但上线前一定要改成精确地址
  • 定期review CSP配置,删除不再使用的域名

这里分享一个调试小工具,Chrome浏览器自带的CSP检查功能:

chrome://net-internals/#csp

能帮你快速定位哪些请求被拦截了,比看日志方便多了。

以上是我总结的最佳实践

connect-src这块水还挺深的,每个项目情况都不一样。我目前用的这套方案也不是完美的,但至少能cover住大部分场景。如果你有更好的实践经验,欢迎评论区交流。

最后提醒一句:改动CSP配置后,记得要充分测试。我就遇到过改完后某些边缘case还是有问题的情况,这时候只能具体情况具体分析了。

本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。
发表评论

暂无评论