经过以上设置,浏览器发送实际请求时会向服务器发送 Cookies,同时服务器也需要在响应中设置
Access-Control-Allow-Credentials 响应头
res.writeHead(200, {'Access-Control-Allow-Origin': 'http://127.0.0.1:3010','Access-Control-Allow-Credentials': true }); 如果服务端不设置浏览器就不会正常响应,会报一个跨域错误,如下所示:
Access to fetch at 'http://127.0.0.1:3011/api/data' from origin 'http://127.0.0.1:3010' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'.
还有一点需要注意,如果我们在请求中设置了 credentials: "include" 服务端就不能设置
Access-Control-Allow-Origin: "*" 只能设置为一个明确的地址 。
本节代码示例:
github.com/qufei1993/http-protocol/tree/master/example/cors/03 解决跨域问题的几种方法通过上面的分析了解跨域产生的原因之后,解决其实并不难,上面的讲解中其实也提供了解决方案,例如在 Node.js 中我们可以设置响应头部字段
Access-Control-Allow-Origin、Access-Control-Expose-Headers、Access-Control-Allow-Methods 等,但是在实际开发中这样设置难免繁琐,下面介绍几种常用的解决方法 。
使用 CORS 模块
在 Node.js 中推荐你使用 cors 模块 github.com/expressjs/cors[3] 。
在我们本节的示例中,一直使用的 Node.js 原生模块来编写我们的示例,在引入 cors 模块后,可以按照如下方式改写:
const http = require('http'); const PORT = 3011; const corsMiddleware = require('cors')({origin: 'http://127.0.0.1:3010',methods: 'PUT,DELETE',allowedHeaders: 'Test-CORS, Content-Type',maxAge: 1728000,credentials: true, });http.createServer((req, res) => {const { url, method } = req;console.log('request url:', url, ', request method:', method);const nextFn = () => {if (method === 'PUT' && url === '/api/data') {return res.end('ok!');}return res.end();}corsMiddleware(req, res, nextFn); }).listen(PORT); cors 在预检请求之后或在预检请求里并选项中设置了 preflightContinue 属性之后才会执行 nextFn 这个函数,如果预检失败就不会执行 nextFn 函数 。
如果你用的 Express.js 框架,使用起来也很简单,如下所示:
const express = require('express') const cors = require('cors') const app = express()app.use(cors()); JSONP浏览器是允许像 link、img、script 标签在路径上加载一些内容进行请求,是允许跨域的,那么 jsonp 的实现原理就是在 script 标签里面加载了一个链接,去访问服务器的某个请求,返回内容 。
<body><script>// fetch('http://127.0.0.1:3011/api/data', {//method: 'PUT',//headers: {//'Content-Type': 'application/json',//'Test-Cors': 'abc',//},//credentials: "include"// });<srcipt src=https://www.isolves.com/it/cxkf/bk/2021-06-09/"http://127.0.0.1:3011/api/data">
