浏览器跨域的细节
Posted 小菜鸡
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浏览器跨域的细节相关的知识,希望对你有一定的参考价值。
关于什么是跨域,一句话可以说清楚,不同协议,不同子域,不同主域, 不同端口。都可以算成跨域。具体的可以去网上进行搜索。
那么今天来说一下具体前后端如何跨域的实现代码。
从前端说起的话
var headers = new Headers(); headers.append(\'Content-Type\', \'application/json\'); headers.append(\'x-node\', \'node\'); fetch(\'http://127.0.0.1:3000/users/login\', { method: \'POST\', headers: headers, body: JSON.stringify({ userName: \'鬼剑士\', userPwd: \'665533\', }) });
比如这段代码跑在localhost:8080的端口上,那么运行以后浏览器会报错如下信息
XMLHttpRequest cannot load http://127.0.0.1:3000/users/login.
Response to preflight request doesn\'t pass access control check: No \'Access-Control-Allow-Origin\' header is present on the requested resource.
Origin \'http://127.0.0.1:8080\' is therefore not allowed access.
总而言之就是说你的服务器的响应没有返回 Access-Control-Allow-Origin 这样的响应头,怎么处理呢那么需要去服务器设置跨域的响应头
设置的代码大致如下:
以express框架举例
var cors = require(\'cors\'); var express = require(\'express\'); var app = express(); app.use(cors());
然后设置完成以后我们继续请求这个接口,那么这时候的响应头会是这样的
有些同学可能会问,为什么我们只发送了一个POST请求,但是出来一个options请求?
这里请看另一篇博文 http://www.cnblogs.com/web-alibaba/p/7583323.html
接下来就可以愉快的运行了。
但是有些同学有问题了,你这样的话岂不是请求体里不能带上cookie了,每次都要手动加。多麻烦呀。
那么解决这个问题的办法是在我们的fetch函数里添加一个选项 credentials, 简单介绍一下credentials。
这个是为了跨域请求时候控制浏览器的cookie所设计的。参数有三个分别是
omit:永远不带cookie。
same-origin: 请求地址和网页的地址在同一个源下就发送cookie,反之不发送。
include:永远发送。
那么我们可以在fetch里添加这个选项
Fetch API cannot load http://127.0.0.1:3000/users/login.
Response to preflight request doesn\'t pass access control check: The value of the \'Access-Control-Allow-Origin\' header in the response must not be the wildcard \'*\' when the request\'s credentials mode is \'include\'.
Origin \'http://127.0.0.1:8080\' is therefore not allowed access.
然后愉快的发现又报错了。解释一下错误,当浏览器设置了credentials属性的时候 相应的服务器也需要去设置credentials属性。
并且 Access-Control-Allow-Origin的域名不能为*,需要指定具体的域名
那么我们服务端的代码改动成如下
app.use(cors({ origin: \'http://127.0.0.1:8080\', credentials: true, }));
然后看一下cors内部的实现,会发现 credentials为true的时候会返回相应的响应头,浏览器得到以后就会乖乖的不报错了。
function configureCredentials(options) { // 是否带cookies if (options.credentials === true) { return { key: \'Access-Control-Allow-Credentials\', value: \'true\' }; } return null; }
然后发现终于成功了,成功的得到了我们想要的json数据
大概的流程就到这里了。接下来会解析node-cors这个模块。
以上是关于浏览器跨域的细节的主要内容,如果未能解决你的问题,请参考以下文章