加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Ajax跨域、Json跨域、Socket跨域和Canvas跨域等同源策略限制的解

发布时间:2020-12-15 21:36:50 所属栏目:百科 来源:网络整理
导读:同源是指相同的协议、域名、端口,三者都相同才属于同域。不符合上述定义的请求,则称为跨域。 相信每个开发人员都曾遇到过跨域请求的情况,虽然情况不一样,但问题的本质都可以归为浏览器出于安全考虑下的同源策略的限制。 跨域的情形有很多,最常见的有Aja

同源是指相同的协议、域名、端口,三者都相同才属于同域。不符合上述定义的请求,则称为跨域。

相信每个开发人员都曾遇到过跨域请求的情况,虽然情况不一样,但问题的本质都可以归为浏览器出于安全考虑下的同源策略的限制。

跨域的情形有很多,最常见的有Ajax跨域、Socket跨域和Canvas跨域。下面列举一些我们常见的跨域情形下,某些浏览器控制台给出的错误提示:

FireFox下的提示:

已阻止交叉源请求:同源策略不允许读取***上的远程资源。可以将资源移动到相同的域名上或者启用 CORS 来解决这个问题。

Canvas跨域Chrome下的提示:

UncaughtSecurityError:Failedto execute'getImageData'on'CanvasRenderingContext2D':Thecanvas has been taintedbycross-origin data.

或:

Imagefrom origin 'http://js.xx.com' has been blocked from loading by Cross-OriginResource Sharing policy: No 'Access-Control-Allow-Origin' header is present onthe requested resource. Origin 'http://act.xx.com' is therefore not allowedaccess.


网上有许多解决跨域的方法,大体上有这几种:

1)document.domain+iframe的设置

2)动态创建script

3)利用iframe和location.hash

4)window.name实现的跨域数据传输

5)使用HTML5 postMessage

6)利用flash

7)通过代理,js访问代理,代理转到不同的域

http://developer.yahoo.com/javascript/howto-proxy.html

8)Jquery JSONP(不能成为真正的Ajax,本质上仍是动态创建script)

http://www.cnblogs.com/chopper/archive/2012/03/24/2403945.html

9)跨域资源共享(CORS) 这是HTML5跨域问题的标准解决方案

说明:方案1~方案6见Rain Man所写的文章《JavaScript跨域总结与解决办法》

http://www.cnblogs.com/rainman/archive/2011/02/20/1959325.html

下面主要就我总结的几种解决跨域的方法,展开说一下。

1) 绕开跨域。

适用情形是:动静分离。

example1.com域名下的页面中跨域请求是以JavaScript内联方式实现的,而请求的目标静态资源是放在example2.com域名下,这时可以将执行跨域请求的JavaScript代码块独立出来,放到example2.com上,而example1.com页面通过外联方式引入该静态域名下的js文件。这样,js与请求的图片等资源都在example2.com下,即可正常访问到。这种方法其实是一种巧妙避开跨域的方法。

2) 后台抓取克隆图片。

适用情形:动静不分离(两个域名均运行访问静态资源)。

example1.com请求example2.com下的资源图片,可以使用PHP抓取图片并在example2.com下生成一份,这样就可以间接访问到example1.com的静态资源。

html模板示例代码:

$("#scratchpad").wScratchPad({ //刮刮卡示例,当前域名http://act.xxx.com

width:283,

height:154,51); font-family:Arial; font-size:14px; line-height:26px"> //color: "#a9a9a7",51); font-family:Arial; font-size:14px; line-height:26px"> image2:"imgdata.php?url=http://js.xxx.com/static/activity/sq/guagua315/images/card_inner.jpg",51); font-family:Arial; font-size:14px; line-height:26px"> scratchMove:function() {

}

});

xi=newXMLHttpRequest();

xi.open("GET","imgdata.php?url="+yourImageURL,true);

xi.send();

xi.onreadystatechange=function() {

if(xi.readyState==4&& xi.status==200) {

img=Image;

img.onload=function(){

ctx.drawImage(img,0,canvas.width,canvas.height);

}

img.src=xi.responseText;

}

PHP处理代码:

<?php//imgdata.php

$url=$_GET['url'];

$img =file_get_contents($url);

$imgname = substr(strrchr($url,"/"),1);

file_put_contents($fn,$img);

echo $imgname;

?>

上述代码在当前php目录下生成了克隆生成了一张图片。

3) 后台程序设置Access-Control-Allow-Origin

适用情形:Ajax获取跨域接口的JSON数据。

example1.com请求example2.com的数据接口,则需要在example2.com的数据接口添加跨域访问授权。

PHP程序中开始出添加header('HeaderName:HeaderValue'); 这样的header标记:

header('Access-Control-Allow-Origin:*');

4)修改服务器配置启用CORS

适用情形:跨域访问静态资源。

Access-Control-Allow-Origin是什么作用呢?用于授权资源的跨站访问。比如,静态资源图片都放在example2.com 域名下,如果在返回的头中没有设置 Access-Control-Allow-Origin,那么别的域是没有权限外链你的图片的。

要实现CORS跨域,服务端需要这个一个流程,图片引自html5rocks,附图如下

a.对于简单请求,如GET,只需要在HTTP Response后添加Access-Control-Allow-Origin。

b.对于非简单请求,比如POST、PUT、DELETE等,浏览器会分两次应答。第一次preflight(method: OPTIONS),主要验证来源是否合法,并返回允许的Header等。第二次才是真正的HTTP应答。所以服务器必须处理OPTIONS应答。

这里是一个nginx启用CORS的参考配置示例http://enable-cors.org/server_nginx.html。代码:

[plain] view plain copy
  1. #
  2. #ACORS(Cross-OriginResouceSharing)configfornginx
  3. #
  4. #==Purpose
  5. #ThisnginxconfigurationenablesCORSrequestsinthefollowingway:
  6. #-enablesCORSjustfororiginsonawhitelistspecifiedbyaregularexpression
  7. #-CORSpreflightrequest(OPTIONS)arerespondedimmediately
  8. #-Access-Control-Allow-Credentials=trueforGETandPOSTrequests
  9. #-Access-Control-Max-Age=20days,tominimizerepetitiveOPTIONSrequests
  10. #-varioussuperluoussettingstoaccommodatenonconformantbrowsers
  11. #
  12. #==CommentonechoingAccess-Control-Allow-Origin
  13. #HowdoyouallowCORSrequestsonlyfromcertaindomains?Thelast
  14. #publishedW3Ccandidaterecommendationstatesthatthe
  15. #Access-Control-Allow-Originheadercanincludealistoforigins.
  16. #(See:http://www.w3.org/TR/2013/CR-cors-20130129/#access-control-allow-origin-response-header)
  17. #However,browsersdonotsupportthiswellanditlikelywillbe
  18. #droppedfromthespec(see,http://www.rfc-editor.org/errata_search.php?rfc=6454&eid=3249).
  19. #Theusualworkaroundisfortheservertokeepawhitelistof
  20. #acceptableorigins(asaregularexpression),matchtherequest's
  21. #Originheaderagainstthelist,andechobackthematchedvalue.
  22. #(Yesyoucanuse'*'toacceptalloriginsbutthisistooopenand
  23. #preventsusing'Access-Control-Allow-Credentials:true',whichis
  24. #neededforHTTPBasicAccessauthentication.)
  25. #==Commentonspec
  26. #CommentsbelowareallbasedonmyreadingoftheCORSspecasof
  27. #2013-Jan-29(http://www.w3.org/TR/2013/CR-cors-20130129/),the
  28. #XMLHttpRequestspec(
  29. #http://www.w3.org/TR/2012/WD-XMLHttpRequest-20121206/),and
  30. #experimentationwithlatestversionsofFirefox,Chrome,Safariat
  31. #thatpointintime.
  32. #==Changelog
  33. #sharedat:https://gist.github.com/algal/5480916
  34. #basedon:https://gist.github.com/alexjs/4165271
  35. location/{
  36. #iftherequestincludedanOrigin:headerwithanoriginonthewhitelist,
  37. #thenitissomekindofCORSrequest.
  38. #specifically,thisexampleallowCORSrequestsfrom
  39. #scheme:httporhttps
  40. #authority:anyauthorityendingin".mckinsey.com"
  41. #port:nothing,or:
  42. if($http_origin~*(https?://[^/]*.mckinsey.com(:[0-9]+)?)$){
  43. set$cors"true";
  44. }
  45. #Nginxdoesn'tsupportnestedIfstatements,soweusestring
  46. #concatenationtocreateaflagforcompoundconditions
  47. #OPTIONSindicatesaCORSpre-flightrequest
  48. if($request_method='OPTIONS'){
  49. set$cors"${cors}options";
  50. #non-OPTIONSindicatesanormalCORSrequest
  51. if($request_method='GET'){
  52. set$cors"${cors}get";
  53. }
  54. if($request_method='POST'){
  55. set$cors"${cors}post";
  56. #ifit'saGETorPOST,setthestandardCORSresponsesheader
  57. if($cors="trueget"){
  58. #Tellsthebrowserthisoriginmaymakecross-originrequests
  59. #(Here,weechotherequestingorigin,whichmatchedthewhitelist.)
  60. add_header'Access-Control-Allow-Origin'"$http_origin";
  61. #Tellsthebrowseritmayshowtheresponse,whenXmlHttpRequest.withCredentials=true.
  62. add_header'Access-Control-Allow-Credentials''true';
  63. ##TellthebrowserwhichresponseheaderstheJScansee,besidesthe"simpleresponseheaders"
  64. #add_header'Access-Control-Expose-Headers''myresponseheader';
  65. if($cors="truepost"){
  66. #ifit'sOPTIONS,thenit'saCORSpreflightrequestsorespondimmediatelywithnoresponsebody
  67. if($cors="trueoptions"){
  68. #Tellsthebrowserthisoriginmaymakecross-originrequests
  69. #(Here,whichmatchedthewhitelist.)
  70. add_header'Access-Control-Allow-Origin'"$http_origin";
  71. #inapreflightresponse,tellsbrowserthesubsequentactualrequestcanincludeusercredentials(e.g.,cookies)
  72. add_header'Access-Control-Allow-Credentials''true';
  73. #Returnspecialpreflightinfo
  74. #Tellbrowsertocachethispre-flightinfofor20days
  75. add_header'Access-Control-Max-Age'1728000;
  76. #TellbrowserwerespondtoGET,POST,OPTIONSinnormalCORSrequests.
  77. #Notofficiallyneededbutstillincludedtohelpnon-conformingbrowsers.
  78. #OPTIONSshouldnotbeneededhere,sincethefieldisused
  79. #toindicatemethodsallowedfor"actualrequest"notthe
  80. #preflightrequest.
  81. #GET,POSTalsoshouldnotbeneeded,sincethe"simple
  82. #methods"GET,HEADareincludedbydefault.
  83. #Weshouldonlyneedthisheaderfornon-simplerequests
  84. #methods(e.g.,DELETE),orcustomrequestmethods(e.g.,XMODIFY)
  85. add_header'Access-Control-Allow-Methods''GET,OPTIONS';
  86. #Tellbrowserweaccepttheseheadersintheactualrequest
  87. #Adynamic,wide-openconfigwouldjustechobackalltheheaders
  88. #listedinthepreflightrequest's
  89. #Access-Control-Request-Headers.
  90. #subsetofAccess-Control-Request-Headersheaderswhichare
  91. #allowedforthisresource.
  92. #Thisstatic,fairlyopenconfigjustreturnsahardcodedsetof
  93. #headersthatcoversmanycases,includingsomeheadersthat
  94. #areofficiallyunnecessarybutactuallyneededtosupport
  95. #non-conformingbrowsers
  96. #Commentonsomeparticularheadersbelow:
  97. #Authorization--practicallyandofficiallyneededtosupport
  98. #requestsusingHTTPBasicAccessauthentication.BrowserJS
  99. #canuseHTTPBAauthenticationwithanXmlHttpRequestobject
  100. #reqbycalling
  101. #req.withCredentials=true,248)"> #req.setRequestHeader('Authorization','Basic'+window.btoa(theusername+':'+thepassword))
  102. #Counterintuitively,theusernameandpasswordfieldson
  103. #XmlHttpRequest#opencannotbeusedtosettheauthorization
  104. #fieldautomaticallyforCORSrequests.
  105. #Content-Type--thisisa"simpleheader"onlywhenit's
  106. #valueiseitherapplication/x-www-form-urlencoded,248)"> #multipart/form-data,ortext/plain;andinthatcaseitdoes
  107. #notofficiallyneedtobeincluded.But,ifyourbrowser
  108. #codesetsthecontenttypeasapplication/json,forexample,
  109. #thenthatmakestheheadernon-simple,andthenyourserver
  110. #mustdeclarethatitallowstheContent-Typeheader.
  111. #Accept,Accept-Language,Content-Language--thesearethe
  112. #"simpleheaders"andtheyareofficiallynever
  113. #required.Practically,possiblyrequired.
  114. #Origin--logically,shouldnotneedtobeexplicitly
  115. #required,sinceit'simplicitlyrequiredbyallof
  116. #CORS.officially,itisunclearifitisrequiredor
  117. #forbidden!practically,probablyrequiredbyexisting
  118. #browsers(GeckodoesnotrequestitbutWebKitdoes,so
  119. #WebKitmightchokeifit'snotreturnedback).
  120. #User-Agent,DNT--officially,shouldnotberequired,as
  121. #theycannotbesetas"authorrequestheaders".practically,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> #mayberequired.
  122. #MyComment:
  123. #Thespecsarecontradictory,orelsejustconfusingtome,248)"> #inhowtheydescribecertainheadersasrequiredbyCORSbut
  124. #forbiddenbyXmlHttpRequest.TheCORSspecsaysthebrowser
  125. #issupposedtosetAccess-Control-Request-Headerstoinclude
  126. #only"authorrequestheaders"(section7.1.5).Andthenthe
  127. #serverissupposedtouseAccess-Control-Allow-Headersto
  128. #echobackthesubsetofthosewhichisallowed,tellingthe
  129. #browserthatitshouldnotcontinueandperformtheactual
  130. #requestifitincludesadditionalheaders(section7.1.5,248)"> #step8).Sothisimpliesthebrowserclientcodemusttake
  131. #caretoincludeallnecessaryheadersasauthorrequest
  132. #headers.
  133. #However,thespecforXmlHttpRequest#setRequestHeader
  134. #(section4.6.2)providesalonglistofheaderswhichthe
  135. #thebrowserclientcodeisforbiddentoset,includingfor
  136. #instanceOrigin,DNT(donottrack),User-Agent,etc..This
  137. #isunderstandable:theseareallheadersthatwewantthe
  138. #browseritselftocontrol,sothatmaliciousbrowserclient
  139. #codecannotspoofthemandforinstancepretendtobefroma
  140. #differentorigin,etc..
  141. #ButifXmlHttpRequestforbidsthebrowserclientcodefrom
  142. #settingthese(aspertheXmlHttpRequestspec),thenthey
  143. #arenotauthorrequestheaders.Andiftheyarenotauthor
  144. #requestheaders,thenthebrowsershouldnotincludethemin
  145. #thepreflightrequest'sAccess-Control-Request-Headers.And
  146. #iftheyarenotincludedinAccess-Control-Request-Headers,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> #thentheyshouldnotbeechoedby
  147. #Access-Control-Allow-Headers.Andiftheyarenotechoedby
  148. #Access-Control-Allow-Headers,thenthebrowsershouldnot
  149. #continueandexecuteactualrequest.Sothisseemstoimply
  150. #thattheCORSandXmlHttpRequestspecsforbidcertain
  151. #widely-usedfieldsinCORSrequests,includingtheOrigin
  152. #field,whichtheyalsorequireforCORSrequests.
  153. #Thebottomline:itseemsthereareheadersneededforthe
  154. #webandCORStowork,whichatthemomentyoushould
  155. #hard-codeintoAccess-Control-Allow-Headers,although
  156. #officialspecsimplythisshouldnotbenecessary.
  157. add_header'Access-Control-Allow-Headers''Authorization,Content-Type,Accept,Origin,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since';
  158. #buildentireresponsetothepreflightrequest
  159. #nobodyinthisresponse
  160. add_header'Content-Length'0;
  161. #(shouldnotbenecessary,butincludedfornon-conformingbrowsers)
  162. add_header'Content-Type''text/plaincharset=UTF-8';
  163. #indicatesuccessfulreturnwithnocontent
  164. return204;
  165. #--PUTYOURREGULARNGINXCODEHERE--

服务器解析流程如下:

a.首先查看http头部有无origin字段;

b.如果没有,或者不允许,直接当成普通请求处理,结束;

c.如果有并且是允许的,那么再看是否是preflight(method=OPTIONS);

d.如果是preflight,就返回Allow-Headers、Allow-Methods等,内容为空;

e.如果不是preflight,就返回Allow-Origin、Allow-Credentials等,并返回正常内容。

若服务器为nginx,可以 nginx conf 文件中加入以下内容:

    location/{
  1. add_headerAccess-Control-Allow-Origin*;
  2. }

若服务器为Apache,则可以按照如下配置:

    <IfModulemod_setenvif.c>
  1. <IfModulemod_headers.c>
  2. <FilesMatch".(cur|gif|ico|jpe?g|png|svgz?|webp)$">
  3. SetEnvIfOrigin":"IS_CORS
  4. HeadersetAccess-Control-Allow-Origin"*"env=IS_CORS
  5. </FilesMatch>
  6. </IfModule>
  7. </IfModule>

为安全起见,Access-Control-Allow-Origin也可设为特定域名的方式。

在HTML5中,有些HTML元素为CORS提供了支持,如img、video新增了crossOrigin属性,属性值可以为anonymoususe-credentials。比如,canvas绘图要用到跨域图片,在JavaScript中要设置img.crossOrigin="Anonymous";

[javascript]
    varimg=newImage,
  1. canvas=document.createElement("canvas"),
  2. ctx=canvas.getContext("2d"),248)"> src="http://example.com/image";//insertimageurlhere
  3. img.crossOrigin="Anonymous";
  4. img.onload=function(){
  5. canvas.width=img.width;
  6. canvas.height=img.height;
  7. ctx.drawImage(img,0);
  8. localStorage.setItem("savedImageData",canvas.toDataURL("image/png"));
  9. img.src=src;
  10. //makesuretheloadeventfiresforcachedimagestoo
  11. if(img.complete||img.complete===undefined){
  12. img.src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
  13. 上述配置完成后,重启服务器,CORS启用。

    然后我们再刷新页面,查询请求头的参数,可以发现多出一个:Access-Control-Allow-Origin:*

    ,到此证明服务器配置已经生效。同时我们的canvas绘图也可以正常使用了。

    刷新页面返回请求响应结果后,HTTP Request Headers的内容:

    Remote Address:222.132.18.xx:80

    Request URL:http://js.xx.com/static/activity/sq/guagua315/images/card_inner.jpg

    Request Method:GET

    Status Code:200 OK

    Request Headersview source

    Accept:image/webp,*/*;q=0.8

    Accept-Encoding:gzip,deflate,sdch

    Accept-Language:zh-CN,zh;q=0.8

    Cache-Control:no-cache

    Connection:keep-alive

    Host:js.xx.com

    Origin:http://act.xx.com

    Pragma:no-cache

    RA-Sid:7CCAD53E-20140704-054839-03c57a-85faf2

    RA-Ver:2.8.8

    Referer:http://act.xx.com/sq/guagua315?uuid=46124642&fid=2&sign=xxx

    User-Agent:Mozilla/5.0 (Windows NT 6.1;WOW64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/40.0.2214.115Safari/537.36

    Response Headersview source

    Accept-Ranges:bytes

    Access-Control-Allow-Origin:*

    Connection:close

    Content-Length:4010

    Content-Type:image/jpeg

    Date:Thu,12 Mar 2015 02:29:43 GMT

    ETag:"54f7d1b4-faa"

    Last-Modified:Thu,05 Mar 2015 03:47:00 GMT

    Powered-By-ChinaCache:MISS fromCNC-WF-3-3X6

    Powered-By-ChinaCache:MISS fromCNC-WF-3-3X5

    Server:Tengine

    Switch:FSCS
    附图:


    参考文章:

    CORS enabled image https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image

    CORS on Nginx http://enable-cors.org/server_nginx.html

    Nginx CORS实现JS跨域 http://www.52php.cn/article/p-xhzdhafc-bbp.html

    转载请注明出处,文章来自于freshlover的CSDN空间《Ajax跨域、Json跨域、Socket跨域和Canvas跨域等同源策略限制的解决方法》

    http://www.52php.cn/article/p-dsqvmmtq-yn.html

    (编辑:李大同)

    【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读