参考链接:
我们俗称的跨域,也就是浏览器的 同源策略,直接看 MDN 的解释吧:
来源:
面试官问到了一个问题:如何解决跨域问题?我巴巴拉拉的一顿说,大概了说了四种方法,然后面试官紧接着又问:那跨域请求怎么携带cookie呢?(常规的面试套路,一般都会顺着你的回答往深了问)由于之前的项目都是同源的,不牵涉跨域访问,所以一时没有回答出来,后来研究了下,所以有了这篇文章。
解决办法:
前端请求时在request对象中配置"withCredentials": true;服务端在response的header中配置"Access-Control-Allow-Origin", "http://xxx:${port}";服务端在response的header中配置"Access-Control-Allow-Credentials", "true"
简单请求
浏览器在对一个url发起简单跨域请求时会在HTTP请求头中设置一个Origin字段,表示浏览器发起请求的来源地址。 服务器需要检查这个来源是否合法,如果合法的话,服务除了需要正常处理业务以外,还需要在HTTP回复的响应头中设置如下字段:
Access-Control-Allow-Origin值和请求头中的Origin字段值一致Access-Control-Allow-Credentials值一般设为字符串类型的true,表示是否允许发送Cookie
非简单请求
非简单请求的处理除了要完成上述对于简单请求的处理之外,还需要一些额外的处理。
浏览器在对一个url发起跨域非简单请求时首先会发出一个相同url的OPTIONS方法的请求,一般我们称之为preflight。然后根据preflight请求的结果再进行实际的请求发送。
浏览器会在preflight的HTTP请求头中设置一个Access-Control-Request-Method字段,用来表示本来实际发起的请求是什么方法。
如果实际的请求头中包含自自定义的字段,那么浏览器在还会在preflight的HTTP请求头中设置一个Access-Control-Request-Headers字段,用来表示实际发起的请求头中将要包含的字段。
对于preflight的处理,服务器此时应返回200,并先对此请求进行简单请求的处理,然后再返回的请求头中设置如下字段:
- Access-Control-Allow-Methods
- 此字段表示服务器针对此url允许哪些方法的请求,一般来说,值可以设为请求头中的Access-Control-Request-Method字段的值。但是最好每次都全部设为GET,POST,PUT,DELETE,OPTIONS,这样可以避免浏览器针对每种方法都发起preflight,提升性能。
- Access-Control-Allow-Headers
- 此字段表示服务器允许接收的请求头的字段,如果浏览器的请求头中有Access-Control-Request-Headers,则将值设置为和请求头中Access-Control-Request-Headers字段的值一致。否则设为字符串类型的*。
当浏览器完成了preflight请求并且服务器给出的响应都正确,浏览器才会发起真正的跨域非简单请求。此时的处理就比较简单了。此时浏览器应该先对此请求进行简单请求的处理,然后按照preflight响应头中关于Access-Control-Allow-Headers的处理规则进行处理即可。
