一个朴实无华的标题:跨域问题笔记

356 阅读3分钟

前端在浏览器环境使用fetch API进行测试

遵守同源策略

任意浏览器窗口在控制台执行它

fetch('http://localhost:3000/test?id=233', {mode: 'same-origin'}).then(r => r.text()).then(console.log)

报错为

Fetch API cannot load http://localhost:3000/test?id=233. Request mode is "same-origin" but the URL's origin is not same as the request origin https://www.bing.com.

原因:

因为fetch限定了该请求需要满足同源所以本次请求未发送出去,在请求阶段被拦截,网络控制台中找不到的

允许跨域

任意浏览器窗口在控制台执行它

fetch('http://localhost:3000') // 等价于fetch('http://localhost:3000', {mode: 'cors'})

报错为:

Access to fetch at 'http://localhost:3000/' from origin 'https://www.bing.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

google translate一下:

CORS 策略已阻止从源“https://www.bing.com”获取“http://localhost:3000/”的访问权限:请求中不存在“Access-Control-Allow-Origin”标头 资源。 如果不透明的响应满足您的需求,请将请求的模式设置为“no-cors”以获取禁用 CORS 的资源。

原因: 当前允许发送跨域请求所以该请求发送了,但是因为服务端未配置CORS头,也就是(Access-Control-Allow-Origin),fetch 给报了个错,所以没有返回值。我也说不好为啥不给响应,有更好的解释请评论

no-cors

任意浏览器窗口在控制台执行它

fetch('http://localhost:3000/test?id=233', {mode: 'no-cors'})

请求发出去了,服务器也可以收到,控制台没有报错了,也有响应对象,但是响应体是空的,且type为opaque,我们也读不到响应体

image.png

默认允许跨域且服务器配置了CORS头

任意浏览器窗口在控制台执行它

fetch('http://localhost:3000').then(res => {console.log([res.type, res.status]) 
    return res.json()}).then(console.log)

这次成功了,且拿到了响应

image.png

响应头长这个样子:(你可以看到他在响应头里添加了上上文所说的Access-Control-Allow-Origin头)

image.png

服务器的CORS配置如下:(这里我使用了CORS中间件,直接在响应的headers中设置该头也是可以的)

image.png

CSP -- Content-Security-Policy

今早在MDN网站发现的,不知道算不算跨域问题,在MDN的网页控制台中执行:

fetch('http://localhost:3000') // 等价于fetch('http://localhost:3000', {mode: 'cors'})

报错为:

Refused to connect to 'http://localhost:3000/' because it violates the following Content Security Policy directive: "connect-src 'self' updates.developer.allizom.org updates.developer.mozilla.org www.google-analytics.com stats.g.doubleclick.net".

找到关键字Content Security Policy,这个没啥办法啦,这个是网页响应中的响应头该页可访问的源,不是限定中的源不发送网络请求。

总结

暴论:前端(浏览器)就纯纯的解决不了跨域好吧,就是服务器需要配置的😅

然后这个文章是这样诞生的:

想搞个东西需要前后端同时开发 --> 想到了有个跨域问题 --> 好个奇到底咋回事 --> 使用a标签无果 --> 想到了fetch --> 熟练的跨域报错了 --> 看到了no-cors关键字 --> 好奇到底是个啥玩意 --> 好像懂了但是没解决实际问题 --> 原来服务端配置CORS头就可以了 --> 貌似还了解到了CSRF攻击可能之后也写一篇