跨域限制仅仅是浏览器的行为吗#
是的。
跨域限制是浏览器为了信息安全所产生的规则。
跨域问题其实就是浏览器的同源策略导致的。
而利用 nodejs 发送请求是不存在跨域问题的,因为都没有当前域的概念。
浏览器的同源策略#
同源策略是一个重要的安全策略,它用于限制一个 origin 的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。 --来源 MDN
同源的判断:protocol(协议)、domain(域名)、port(端口)三者一致。
浏览器的跨域限制有哪些#
对于不同源的站点,浏览器会有以下限制:
不允许直接请求跨域接口
- 不允许发送 POST 请求:在发送 POST 请求之前会发送 OPTIONS 请求,HTTP 响应状态码为 403(Forbidden)
- 允许发送 GET 请求:HTTP 响应状态码为 200,但是不能读取服务器返回的数据(使用
<img/>
发送 GET 请求)
不允许访问跨域的 DOM,Cookie,XMLHttpRequest
不能访问跨源 localStorage,sessionStorage
浏览器会使用当前域名作为 key 来存数据
所以,由于浏览器 同源策略,非同源的 js 代码
- 无法直接在非同源网站发送跨域请求。
- 无法自己读取非同源 iframe 页面的 DOM 内容,包括 DOM 种的信息。
- 无法访问非同源网站在本地存储的数据
近几年浏览器对于 CSRF 的防御提升,跨域请求携带 cookie 存在限制#
下图是我用常规手段配置跨域后,设置 cookie 时 chrome 的错误提示:
新版 Chrome(Chrome 80+)会对跨域请求携带 cookie 进行以下校验,只有全通过后才可以跨域携带 cookie:
- 服务端 cookie 设置 SameSite=None
- 服务端 cookie 设置 Secure
- 请求通过 https 协议进行
解决跨域#
跨域限制是浏览器为了信息安全所产生的规则
所以 纯前端解决跨域的方案都是不可靠的
其实最直白的方式就是,服务器告诉浏览器,当前域名是可以从我这获取数据的。
也就是配置 response.header
的 Access-Control-Allow-Origin
。
当然处于安全考虑还是不建议设为*
,也就是允许所有域名的请求。这样设置,直接关闭了浏览器跨域请求当前服务的安全控制
建议解决方案:#
- 设置一个请求域名白名单:
- 可以直接在 Nginx 反代理时判断请求 origin 是否在白名单中,从而转发到真实的应用服务器。当然此时的应用服务器需要直接设置
Access-Control-Allow-Origin
为*
或者域名白名单。 - 或者直接在应用服务里利用 middleware 判断 origin 是否在白名单中,来控制请求是否被 forbidden