为什么我自己开发一个能发送请求的网页,无法保存到本地直接使用?
先说答案,当然最根本的原因就是跨域了。 我在再进一步思考一下,这个跨域和平时开发中遇到的跨域,有没有什么不一样? 为什么没有见过别人这么分发自己的应用?应该是有什么问题点的。
先说结论
因为如果后端要允许 file 协议能不发生跨域,需要设置 Access-Control-Allow-Origin: null, 这样会过度放宽跨域权限,可能被攻击者利用。
细说为啥
我开发中遇到的跨域主要就这么2种情况:
- 不同域名,比如从
a.jiahim.com访问b.jiahim.com - 其他情况比如端口啥的,比如端口什么的因为没有遇到,就不展开讲,需要了解跨域的小伙伴可以去百度或者问问大模型 浏览器通源策略 ,都能回答的很好
基于通源策略,如果需要跨域,则要在反向代理中将新域名加入到反向代理的白名单中。
而如果要支持 file 协议的访问,只能将 Access-Control-Allow-Origin 设置为 null。
说到这里,我们就要区分下Access-Control-Allow-Origin能设置什么值?
- 具体域名,比如
Access-Control-Allow-Origin: https://jiahim.com - 通配符,比如
Access-Control-Allow-Origin: *;注意这里不能与Access-Control-Allow-Credentials: true同时使用(浏览器会拒绝携带凭据的请求)。 - 这里提到的 null,
Access-Control-Allow-Origin: null,允许 Origin: null 的请求(如本地 file:// 协议打开的 HTML 文件),生产环境一定不能用这个。
当本地文件使用 file:// 协议打开的文件发送网络请求时,浏览器会将请求的 Origin 设置为 null,所以后端要支持,也需要设置 Access-Control-Allow-Origin: null。
当后端设置为 null 时,前端发送的请求是可以携带凭据的,这意味着,任何人,都可以在本地打开 html 静态页面,并且使用带有登录态的信息访问服务,攻击者甚至可以构造危险的文件发起攻击,浏览器的安全机制在这里也就失去了效果。
至此,基本就清晰了:
- 本地文件使用
file://协议打开, 发送的网络请求的 Origin 是 null - 后端如果要让前端不触发浏览器的 CORS,需要把
Access-Control-Allow-Origin设置为null - 设置为 null 后,攻击者可以诱骗用户下载一个恶意 HTML 文件(例如伪装成文档或工具),用户双击打开后(通过 file:// 协议运行),该文件可以自由访问你的服务。 哦吼,这不就 G 了吗?不安全啊
所以,看完知道为啥不能了吗?
