资讯专栏INFORMATION COLUMN

前端跨域策略实践----cors,jsonp

Taste / 3401人阅读

摘要:浏览器端需要设置响应头的,,等字段,指定允许的方法,头部,源等信息。可以通过前后端约定一个字段名,比如,来传递一个函数名,从而使得前端可以使用对应的函数,拿到数据,处理数据。

原文地址:https://github.com/HolyZheng/...

了解几个跨域的方案,并且通过简单实践进行体会。

如何实践?

但是,我们如何进行实践呢?在哪发请求?向什么服务器发请求?很简单,就在当前网页,打开控制台,输入请求的代码

var url = "http://127.0.0.1:8888/";
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.send();

那么我们就可以以当前页面url作为origin,向http://127.0.0.1:8888/ ,发送请求GET请求了。
同时在本地创建一个node服务

var http = require("http");

http.createServer(function (request, response) {

    response.writeHead(200, {
      "Content-Type": "text/plain"
    });

    response.end("request success!!!");
}).listen(8888);

console.log("Server running at http://127.0.0.1:8888/");

这样我们就有服务器了,你可以很轻松的跟着这遍文章来实践了,然后从当前网页发送get请求到本地服务,理所当然跨域了。

ps: github网站不行(本文最初再github上编写),会引发csp错误,此错误是用于防止内容注入攻击的,不得不说,大网站安全措施做得就是好,转战segmentfault做实践。

1. cors

cors(跨域资源共享 Cross-origin resource sharing),它允许浏览器向跨域服务器发出XMLHttpRequest请求,从而克服跨域问题,它需要浏览器和服务器的同时支持。

cors 分为两种请求,简单请求和非简单请求,关于cors的更详细介绍,推荐阮一峰老师的跨域资源共享 CORS 详解,本文注重实践。
简单请求

正如上方的例子便是一个简单请求

var url = "http://127.0.0.1:8888/";
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.send();

如何解决此案例的跨域问题呢?
浏览器端,浏览器会自动在请求头中添加 origin 字段,我们不需要操作。

Request Headers: 
Origin: https://github.com

服务端,Access-Control-Allow-Origin属性,我们需要服务端设置此属性,指定允许的请求源域名,可以通过指定为 *来指定所以域名。后端动起来:

var http = require("http");

http.createServer(function (request, response) {

    response.writeHead(200, {
      "Content-Type": "text/plain",
      "Access-Control-Allow-Origin": "*"
    });

    response.end("request success!!!");
}).listen(8888);

console.log("Server running at http://127.0.0.1:8888/");

重启服务,再尝试


这次没有再报错了,我们看看服务器放回了什么

nice!跨域成功!

非简单请求

同样我们在控制台输入一下代码进行put(非简单请求)

var url = "http://127.0.0.1:8888/";
var xhr = new XMLHttpRequest();
xhr.open("PUT", url, true);
xhr.send();

毫无意外的报错

在进行非简单请求的时候,浏览器会先发送一次OPTION请求来“预检”(preflight)该请求是否被允许,请求头中会通过Access-Control-Request-MethodAccess-Control-Request-Headers来告诉服务器我需要用到的方法和字段,服务器通过返回的头部信息中的Access-Control-Allow-OriginAccess-Control-Allow-Method来告诉浏览器该跨域请求是否被允许。修改后端代码:

var http = require("http");

http.createServer(function (request, response) {

    response.writeHead(200, {
      "Content-Type": "text/plain",
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Methods": "GET, POST, PUT"
    });

    response.end("request success!!!");
}).listen(8888);

console.log("Server running at http://127.0.0.1:8888/");

可以看到浏览器会先发送一个预检

当确认允许跨域之后,以后再发送该请求,就会省去预检处理,之间当作简单请求来操作。很明显,修改了后端代码后,这次的put请求时成功的。这里就不继续上图了。

cors总结

cors(跨域资源共享 Cross-origin resource sharing),它允许浏览器向跨域服务器发出XMLHttpRequest请求,从而克服跨域问题,它需要浏览器和服务器的同时支持。

浏览器端会自动向请求头添加origin字段,表明当前请求来源。

浏览器端需要设置响应头的Access-Control-Allow-MethodsAccess-Control-Allow-HeadersAccess-Control-Allow-Origin等字段,指定允许的方法,头部,源等信息。

请求分为简单请求和非简单请求,非简单请求会先进行一次OPTION方法进行预检,看是否允许当前跨域请求。

2. jsonp

jsonp的原理就是利用就是利用script标签没有跨域限制,可以通过script标签的src属性发送GET请求。我们继续尝试,先把后端有关跨域的设置去掉,并重启服务

var http = require("http");

http.createServer(function (request, response) {

    response.writeHead(200, {
      "Content-Type": "text/plain"
    });

    response.end("request success!!!");
}).listen(8888);

console.log("Server running at http://127.0.0.1:8888/");

打开我们的控制台输入一下代码,利用script标签进行jsonp请求

var script = document.createElement("script");
script.type = "text/javascript";
script.src = `http://127.0.0.1:8888/`;
document.head.appendChild(script);

可以看到,后端正常的返回了

request success !!!

而且该请求为GET请求

Request URL: http://127.0.0.1:8888/
Request Method: GET
Status Code: 200 OK
Remote Address: 127.0.0.1:8888
Referrer Policy: no-referrer-when-downgrade

但是我们现在只是成功发送了一个跨域请求,但是我们不像XMLHttpRequest那样可以在res.responseText中拿到数据,通过jsonp我们该怎么拿到请求的数据呢?方法就是前后端约定一个callback字段名,来传递函数名,前端通过该函数来拿到数据。前端代码修改为:

var script = document.createElement("script");
script.type = "text/javascript";
script.src = `http://127.0.0.1:8888/?callback=onBack`;
document.head.appendChild(script);
function onBack (res) {
  console.log(JSON.stringify(res));
  // 请求完后删除添加到页面上的script标签
  var head = document.head
  head.removeChild(script)
}

通过callback字段来传递函数名onBack,后端代码修改为

var http = require("http")
var urlTool = require("url")
// json 数据
var data = {"methods": "jsonp", "result": "success"};

http.createServer(function (request, response) {
    var params = urlTool.parse(request.url, true)
    console.log(params)
    response.writeHead(200, {
      "Content-Type": "text/plain"
    });
    if (params.query && params.query.callback) {

      // callback(data)
      var str = `${params.query.callback}(${JSON.stringify(data)})`
    }

    response.end(str);
}).listen(8888);

console.log("Server running at http://127.0.0.1:8888/");

重启后端服务,并且在控制台输入代码,可以看到结果:

我们拿到了数据,并且通过onBack函数将他输出到了控制台上!

总结

jsonp是一种跨域方案,他利用script标签没有跨域限制的特点,通过script标签的的src属性发送GET请求。

可以通过前后端约定一个字段名,比如callback,来传递一个函数名,从而使得前端可以使用对应的callback函数,拿到数据,处理数据。

jsonp和cors比较

CORS与JSONP的使用目的相同,但是比JSONP更强大。

JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。

同源策略:同源策略限制了一个源(origin)中加载文本或脚本与来自其它源(origin)中资源的交互方式,这是一个用于隔离潜在恶意文件的重要安全机制。如果两个页面拥有 相同 的 协议(protocol),端口(如果指定),和 主机,那么这两个页面就属于同一个源(origin)。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95869.html

相关文章

  • 同源策略跨域资源共享的纠缠

    摘要:扯了这么多,自然不是为了吹水,而是要为了引出前端开发的一个重要的知识点同源策略什么是同源策略出于保护用户信息安全的目的,现在的浏览器都会实施同源策略这个政策,所谓同源策略指的是不同源的客户端脚本在没有明确授权情况下,不允许读写对方的资源。 导语你家的小孩带了他的朋友来你们的家里玩,你家的小孩如果要在自家屋里拿玩具玩、拿东西吃你自然是不会阻止,但是如果你家小孩的朋友人品不行,乱拿东西吃、...

    alighters 评论0 收藏0
  • 同源策略跨域资源共享的纠缠

    摘要:扯了这么多,自然不是为了吹水,而是要为了引出前端开发的一个重要的知识点同源策略什么是同源策略出于保护用户信息安全的目的,现在的浏览器都会实施同源策略这个政策,所谓同源策略指的是不同源的客户端脚本在没有明确授权情况下,不允许读写对方的资源。 导语你家的小孩带了他的朋友来你们的家里玩,你家的小孩如果要在自家屋里拿玩具玩、拿东西吃你自然是不会阻止,但是如果你家小孩的朋友人品不行,乱拿东西吃、...

    赵连江 评论0 收藏0
  • 004. 前端跨域资源请求: JSONP/CORS/反向代理

    摘要:同源策略浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。不受同源策略限制的跨域资源的引入是允许的页面中的链接,重定向以及表单提交是不会受到同源策略限制的。1.什么是跨域资源请求? https://www.cnblogs.com/niuli1987/p/10252214.html 同源: 如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相...

    番茄西红柿 评论0 收藏0
  • 关于跨域

    摘要:经历了几场笔试面试,屡次被问到关于如何实现跨域。转自个人博客关于跨域什么是跨域一般来说,如果你在开发中需要进行跨域操作从一个非同源网站发送请求获取数据,一般而言,你在浏览器控制台看到的结果为同源策略说到跨域就不得不提同源策略。 前言 转眼就是秋招季啦。经历了几场笔试面试,屡次被问到关于如何实现跨域。老实说,之前都是纸上谈兵,也没有项目需要跨域,甚至觉得这个东西没什么意义。直到今天项目中...

    CoreDump 评论0 收藏0

发表评论

0条评论

Taste

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<