解决跨域问题笔记

跨域问题常遇常新,每次都觉得再也不会有问题了,结果过几天又会掉进新坑。

因为种种原因,最近一个项目需要跨域请求 API。然后就随手设置了一下,结果 GET 没问题,POST 就不行,很明显是撞到跨域墙上了。

最后发现原因:

  1. 我们启用了 basic auth 验证用户身份
  2. OPTIONS 也会被要求验证
  3. 预请求失败,后面的正式请求就不会发出

趁着还没忘,总结一下跨域的处理过程:

  1. 首先,熟读《MDN HTTP访问控制(CORS)》
  2. 跨域时,复杂请求(除 HEADGETPOST) API 需要返回 CORS 头
  3. 发起复杂请求前,会发送一个 preflight 请求,也就是 OPTIONS,很多坑都在这个请求上
  4. OPTIONS 是浏览器自动发送的,不受我们控制,在开发者工具的 Network 面板里也看不到。我们经常需要模拟它,检查返回是否符合预期。请求头在后面。
  5. OPTIONS 无法处理 Basic auth,如果开了的话,要做特殊处理
  6. 需要返回 Access-Control-Allow-Origin 允许跨域的域名,简单点可以写 *,但如果要上传 cookie(withCredential: true),则必须写明域名,且只能是 一个 域名
  7. 所以如果有多个域名要跨域访问 API,需要在服务器端判断来源,并返回不同的域名
  8. 如果要上传 cookie,需要在请求时声明 withCredential: true
  9. 服务器还要返回许可的方法,即 Access-Control-Allow-Methods: GET, DELETE, PATCH 等,让浏览器判断
  10. 如果前面都通过了,浏览器才会发送正式请求。如果正式请求失败,则看不到任何返回。

测试 OPTIONS 请求头

OPTIONS /resource/foo 
Access-Control-Request-Method: DELETE 
Access-Control-Request-Headers: origin, x-requested-with
Origin: https://foo.bar.org

如果您觉得文章内容对您有用,不妨支持我创作更多有价值的分享:


已发布

分类

来自

标签:

评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据