首页 > 编程知识 正文

jsonp如何实现跨域,jsonp跨域原理详解

时间:2023-05-05 12:34:38 阅读:9943 作者:183

前端时间一直在做跨域请求方面的工作,遇到一些问题,最后不得不用jsonp方式请求数据。 直到今天,我在网上看到了jsonp的实现原理,发现至今为止的跨域问题没有得到实质性的解决。 幸运的是,看到了一些好的资源,明确了域间相关的问题。

简要介绍jsonp的原理,然后整理如果不使用jsonp,域之间可能出现的问题、解决方法和相关知识点。

一、jsonp 原理

背景:

出于安全考虑,浏览器必须对脚本中的请求执行同源策略检查,并且对于跨域XHR请求,必须在请求的服务的请求标头中设置访问控制-全局-定向标头等。 但是,对于css和script文件的引用等,允许跨域引用。 因此,在常规开发中,可以在html标头中通过link或script标记直接引用特定框架站点的js和css文件。

jsonp 原理:

jsonp技术是利用script可以在域之间自由穿越的特征实现的。 也就是说,dataType为jsonp的请求实际上可以从浏览器的调试窗口看到,实际上是GET类型,因为要创建script标记并通过该标记实现访问。

假设jsonp类型的请求如下:

$.Ajax () URL:'URL )、type:'PUT )、//此处无效的dataType:'jsonp )、Params: ) Param1:'Paramvalue

的实际操作如下

1、连接script标签,script src='url? 使用param1=paramvaluecallbackfunctionname=my callback '/script触发对指定地址的获取请求。 因此,上述设定的type在PUT等中无效)

2、服务器端处理该GET请求,返回字符串' mycallback(data ) );

3、在前端加载该脚本资源后,运行mycallback(data );

4、请求已完成。

二、不用jsonp 的跨域请求

jsonp用script标记方式实现,相当于挖了一个洞。 如何在不使用jsonp的情况下实现域间访问?

首先了解下请求的方式:

1、简单的请求

请求类型为HEAD、GET、POST,是满足一定条件的请求。

2、不是简单的要求

当然是简单请求以外的请求哦。

申请方式详情: dxyz网络博客两种申请方式

两种请求方式的区别:

“印前检查请求”(preflight request )在实际请求之前发送,而“印前检查请求”在通过访问控制检查之后发送。

预检请求不能通过检查情况:

印前检查请求失败可能是因为Origin为空,并显示以下错误:

responsetopreflightrequestdoesn ' tpassaccesscontrolcheck : no ' access-control-allow-origin ' headerispresentonthereqtheqion

紧接着问题,什么情况会导致Origin 为null ?

如果域间请求从域a发送到域b,且域b允许域间请求a,则域c可能重定向到302。 在这种情况下,从域b到域c的跳转请求的Origin为空,并在上面的Origin中提示

关键点,如何解决Origin 为null 问题?

保证两点:

1、域a可以访问域b,域b等可以访问域c (最基本的一点,即首先两个请求直接发送都可以访问,访问-控制-分配-操作

);

2、设置XHR 的withCredentials 为true (必须)。

说明:

第1点是服务器端的设置,第2点是客户端的设置。

服务器端需设置的几个响应头:

Access-Control-Allow-Origin :允许的源,以逗号分隔各源的字符串,如:"www.a.com,www.b.com";

Access-Control-Allow-Methods:允许的请求方式,同上,如:"GET,PUT,POST";

Access-Control-Allow-Credentials:true|false,是否允许传送cookie,需设置为true;

Access-Control-Expose-Headers:允许的请求头。XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。如要想从响应头中获取orgin、accept 头,对应值为:"orgin,accept"。

客户端(即js 代码中)需设置withCredentials 为true:

原始XHR 对象的设置:

var xhr = new XMLHttpRequest();xhr.withCredentials = true;$.ajax 等方法的设置:

$.ajax({url:"url",type:"POST",dataType:"json",xhrFields:{withCredentials:true},//关键params:{param1:"paramValue"},success:function myCallBack(data){...}});


参考:

1、https://bugs.chromium.org/p/chromium/issues/detail?id=154967

里面部分内容:

In the above reproduction steps, the first request's URL is cross-origin, and its origin is the page URL. The response is a 302 redirect with the appropriate access-control-allow-origin="test1.example.org" header so the redirect is allowed to proceed. As part of the redirect steps, the new request origin is set to "null" and it's URL is set to the value of the Location header.The second request generates a response. The only way this second response can pass the resource sharing check is if it contains this header:access-control-allow-origin="*"Furthermore, the original XHR must not have "allow-credentials" set to true.If no header is present, or if specific origins are specified, the response is rejected. The code seems consistent with the standard here.


2、withCredentials 属性作用:https://developer.mozilla.org/zh-CN/search?q=withCredentials

里面部分内容:

he default is false. XMLHttpRequest from a different domain cannot set cookie values for their own domain unless withCredentials is set to true before making the request.翻译:

XMLHttpRequest.withCredentials 默认为false,来自不同域的请求不能为当前域设置cookie,除非该请求的withCredentials 属性在最开始就被设置为true 。

CORS 访问默认是不携带cookie 的,所以当需要传认证等信息时,需要将该属性设置为true。

典型的场景:

单点登录。假设dominC 是用于认证的站点,dominA 与dominB 分别为两个系统,且未登录。当访问dominA 时,可能需要调用dominB 的服务,大致过程为:dominA 中AJAX 发送指向dominB 的请求——>判断到dominB 未登录,遂转到dominC ,生成dominB 的令牌——>从dominC 转回dominB ,并设置相关认证信息(需使用cookie)——>调用原始请求的服务,返回最初的请求者dominA。

上面的过程,请求发送到dominB 时,会302重定向到dominC,所以Origin 会变为null,从而让dominC 不知道最初的请求来源于dominA。但跳转的请求回到dominB 时,需要设置cookie,所以必须在请求的最初发起者(dominA)中设置请求的withCredentials 为true 。

若未设置xhrFields:{withCredentials:true},则可能发生预飞请求错误:

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.


3、跨域资源共享标准文档






版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。