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

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

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

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

FireFox下的提示:

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

Canvas跨域Chrome下的提示:

扫描二维码关注公众号,回复: 1129528 查看本文章

UncaughtSecurityError:Failed to execute‘getImageData’ on ‘CanvasRenderingContext2D’:The canvas has been taintedby cross-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,

         //color: “#a9a9a7”,

         image2:”imgdata.php?url=http://js.xxx.com/static/activity/sq/guagua315/images/card_inner.jpg”,

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=newImage;

    img.onload=function(){

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

    }

    img.src=xi.responseText;

  }

}

PHP处理代码:

<?php//imgdata.php

 

  u r l = _GET[‘url’];

   i m g = f i l e g e t c o n t e n t s ( url);

  i m g n a m e = s u b s t r ( s t r r c h r ( url,“/”),1);

  file_put_contents( f n , 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。代码:

  1. #  
  2. # A CORS (Cross-Origin Resouce Sharing) config for nginx  
  3. #  
  4. # == Purpose  
  5. #  
  6. # This nginx configuration enables CORS requests in the following way:  
  7. # - enables CORS just for origins on a whitelist specified by a regular expression  
  8. # - CORS preflight request (OPTIONS) are responded immediately  
  9. # - Access-Control-Allow-Credentials=true for GET and POST requests  
  10. # - Access-Control-Max-Age=20days, to minimize repetitive OPTIONS requests  
  11. # - various superluous settings to accommodate nonconformant browsers  
  12. #  
  13. # == Comment on echoing Access-Control-Allow-Origin  
  14. #   
  15. # How do you allow CORS requests only from certain domains? The last  
  16. # published W3C candidate recommendation states that the  
  17. # Access-Control-Allow-Origin header can include a list of origins.  
  18. # (See: http://www.w3.org/TR/2013/CR-cors-20130129/#access-control-allow-origin-response-header )  
  19. # However, browsers do not support this well and it likely will be  
  20. # dropped from the spec (see, http://www.rfc-editor.org/errata_search.php?rfc=6454&eid=3249 ).  
  21. #   
  22. # The usual workaround is for the server to keep a whitelist of  
  23. # acceptable origins (as a regular expression), match the request’s  
  24. # Origin header against the list, and echo back the matched value.  
  25. #  
  26. # (Yes you can use ’*’ to accept all origins but this is too open and  
  27. # prevents using ‘Access-Control-Allow-Credentials: true’, which is  
  28. # needed for HTTP Basic Access authentication.)  
  29. #  
  30. # == Comment on  spec  
  31. #  
  32. # Comments below are all based on my reading of the CORS spec as of  
  33. # 2013-Jan-29 ( http://www.w3.org/TR/2013/CR-cors-20130129/ ), the  
  34. # XMLHttpRequest spec (  
  35. # http://www.w3.org/TR/2012/WD-XMLHttpRequest-20121206/ ), and  
  36. # experimentation with latest versions of Firefox, Chrome, Safari at  
  37. # that point in time.  
  38. #  
  39. # == Changelog  
  40. #  
  41. # shared at: https://gist.github.com/algal/5480916  
  42. # based on: https://gist.github.com/alexjs/4165271  
  43. #  
  44.   
  45. location / {  
  46.   
  47.     # if the request included an Origin: header with an origin on the whitelist,  
  48.     # then it is some kind of CORS request.  
  49.   
  50.     # specifically, this example allow CORS requests from  
  51.     #  scheme    : http or https  
  52.     #  authority : any authority ending in ”.mckinsey.com”  
  53.     #  port      : nothing, or :  
  54.     if ( http_origin&nbsp;~*&nbsp;(https?://[^/]*\.mckinsey\.com(:[0-9]+)?) ) {  
  55.         set  cors&nbsp;"true";&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;Nginx&nbsp;doesn't&nbsp;support&nbsp;nested&nbsp;If&nbsp;statements,&nbsp;so&nbsp;we&nbsp;use&nbsp;string&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;concatenation&nbsp;to&nbsp;create&nbsp;a&nbsp;flag&nbsp;for&nbsp;compound&nbsp;conditions&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;OPTIONS&nbsp;indicates&nbsp;a&nbsp;CORS&nbsp;pre-flight&nbsp;request&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;( request_method = ‘OPTIONS’) {  
  56.         set  cors&nbsp;" {cors}options”;    
  57.     }  
  58.   
  59.     # non-OPTIONS indicates a normal CORS request  
  60.     if ( request_method&nbsp;=&nbsp;'GET')&nbsp;{&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set&nbsp;$cors&nbsp;"${cors}get";&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;( request_method = ‘POST’) {  
  61.         set  cors&nbsp;" {cors}post”;  
  62.     }  
  63.   
  64.     # if it’s a GET or POST, set the standard CORS responses header  
  65.     if ( cors&nbsp;=&nbsp;"trueget")&nbsp;{&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;Tells&nbsp;the&nbsp;browser&nbsp;this&nbsp;origin&nbsp;may&nbsp;make&nbsp;cross-origin&nbsp;requests&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;(Here,&nbsp;we&nbsp;echo&nbsp;the&nbsp;requesting&nbsp;origin,&nbsp;which&nbsp;matched&nbsp;the&nbsp;whitelist.)&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add_header&nbsp;'Access-Control-Allow-Origin'&nbsp;"$http_origin";&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;Tells&nbsp;the&nbsp;browser&nbsp;it&nbsp;may&nbsp;show&nbsp;the&nbsp;response,&nbsp;when&nbsp;XmlHttpRequest.withCredentials=true.&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add_header&nbsp;'Access-Control-Allow-Credentials'&nbsp;'true';&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;#&nbsp;Tell&nbsp;the&nbsp;browser&nbsp;which&nbsp;response&nbsp;headers&nbsp;the&nbsp;JS&nbsp;can&nbsp;see,&nbsp;besides&nbsp;the&nbsp;"simple&nbsp;response&nbsp;headers"&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;add_header&nbsp;'Access-Control-Expose-Headers'&nbsp;'myresponseheader';&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;( cors = “truepost”) {  
  66.         # Tells the browser this origin may make cross-origin requests  
  67.         # (Here, we echo the requesting origin, which matched the whitelist.)  
  68.         add_header ‘Access-Control-Allow-Origin’ ” http_origin";&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;Tells&nbsp;the&nbsp;browser&nbsp;it&nbsp;may&nbsp;show&nbsp;the&nbsp;response,&nbsp;when&nbsp;XmlHttpRequest.withCredentials=true.&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add_header&nbsp;'Access-Control-Allow-Credentials'&nbsp;'true';&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;#&nbsp;Tell&nbsp;the&nbsp;browser&nbsp;which&nbsp;response&nbsp;headers&nbsp;the&nbsp;JS&nbsp;can&nbsp;see,&nbsp;besides&nbsp;the&nbsp;"simple&nbsp;response&nbsp;headers"&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;add_header&nbsp;'Access-Control-Expose-Headers'&nbsp;'myresponseheader';&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;if&nbsp;it's&nbsp;OPTIONS,&nbsp;then&nbsp;it's&nbsp;a&nbsp;CORS&nbsp;preflight&nbsp;request&nbsp;so&nbsp;respond&nbsp;immediately&nbsp;with&nbsp;no&nbsp;response&nbsp;body&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;( cors = “trueoptions”) {  
  69.         # Tells the browser this origin may make cross-origin requests  
  70.         # (Here, we echo the requesting origin, which matched the whitelist.)  
  71.         add_header ‘Access-Control-Allow-Origin’ ”$http_origin”;  
  72.         # in a preflight response, tells browser the subsequent actual request can include user credentials (e.g., cookies)  
  73.         add_header ‘Access-Control-Allow-Credentials’ ‘true’;  
  74.   
  75.         #  
  76.         # Return special preflight info  
  77.         #  
  78.           
  79.         # Tell browser to cache this pre-flight info for 20 days  
  80.         add_header ‘Access-Control-Max-Age’ 1728000;  
  81.   
  82.         # Tell browser we respond to GET,POST,OPTIONS in normal CORS requests.  
  83.         #  
  84.         # Not officially needed but still included to help non-conforming browsers.  
  85.         #  
  86.         # OPTIONS should not be needed here, since the field is used  
  87.         # to indicate methods allowed for “actual request” not the  
  88.         # preflight request.  
  89.         #  
  90.         # GET,POST also should not be needed, since the “simple  
  91.         # methods” GET,POST,HEAD are included by default.  
  92.         #  
  93.         # We should only need this header for non-simple requests  
  94.         # methods (e.g., DELETE), or custom request methods (e.g., XMODIFY)  
  95.         add_header ‘Access-Control-Allow-Methods’ ‘GET, POST, OPTIONS’;  
  96.           
  97.         # Tell browser we accept these headers in the actual request  
  98.         #  
  99.         # A dynamic, wide-open config would just echo back all the headers  
  100.         # listed in the preflight request’s  
  101.         # Access-Control-Request-Headers.  
  102.         #  
  103.         # A dynamic, restrictive config, would just echo back the  
  104.         # subset of Access-Control-Request-Headers headers which are  
  105.         # allowed for this resource.  
  106.         #  
  107.         # This static, fairly open config just returns a hardcoded set of  
  108.         # headers that covers many cases, including some headers that  
  109.         # are officially unnecessary but actually needed to support  
  110.         # non-conforming browsers  
  111.         #   
  112.         # Comment on some particular headers below:  
  113.         #  
  114.         # Authorization – practically and officially needed to support  
  115.         # requests using HTTP Basic Access authentication. Browser JS  
  116.         # can use HTTP BA authentication with an XmlHttpRequest object  
  117.         # req by calling  
  118.         #   
  119.         #   req.withCredentials=true,  and  
  120.         #   req.setRequestHeader(‘Authorization’,’Basic ’ + window.btoa(theusername + ’:’ + thepassword))  
  121.         #  
  122.         # Counterintuitively, the username and password fields on  
  123.         # XmlHttpRequest#open cannot be used to set the authorization  
  124.         # field automatically for CORS requests.  
  125.         #  
  126.         # Content-Type – this is a “simple header” only when it’s  
  127.         # value is either application/x-www-form-urlencoded,  
  128.         # multipart/form-data, or text/plain; and in that case it does  
  129.         # not officially need to be included. But, if your browser  
  130.         # code sets the content type as application/json, for example,  
  131.         # then that makes the header non-simple, and then your server  
  132.         # must declare that it allows the Content-Type header.  
  133.         #   
  134.         # Accept,Accept-Language,Content-Language – these are the  
  135.         # “simple headers” and they are officially never  
  136.         # required. Practically, possibly required.  
  137.         #  
  138.         # Origin – logically, should not need to be explicitly  
  139.         # required, since it’s implicitly required by all of  
  140.         # CORS. officially, it is unclear if it is required or  
  141.         # forbidden! practically, probably required by existing  
  142.         # browsers (Gecko does not request it but WebKit does, so  
  143.         # WebKit might choke if it’s not returned back).  
  144.         #  
  145.         # User-Agent,DNT – officially, should not be required, as  
  146.         # they cannot be set as “author request headers”. practically,  
  147.         # may be required.  
  148.         #   
  149.         # My Comment:  
  150.         #  
  151.         # The specs are contradictory, or else just confusing to me,  
  152.         # in how they describe certain headers as required by CORS but  
  153.         # forbidden by XmlHttpRequest. The CORS spec says the browser  
  154.         # is supposed to set Access-Control-Request-Headers to include  
  155.         # only “author request headers” (section 7.1.5). And then the  
  156.         # server is supposed to use Access-Control-Allow-Headers to  
  157.         # echo back the subset of those which is allowed, telling the  
  158.         # browser that it should not continue and perform the actual  
  159.         # request if it includes additional headers (section 7.1.5,  
  160.         # step 8). So this implies the browser client code must take  
  161.         # care to include all necessary headers as author request  
  162.         # headers.  
  163.         #   
  164.         # However, the spec for XmlHttpRequest#setRequestHeader  
  165.         # (section 4.6.2) provides a long list of headers which the  
  166.         # the browser client code is forbidden to set, including for  
  167.         # instance Origin, DNT (do not track), User-Agent, etc.. This  
  168.         # is understandable: these are all headers that we want the  
  169.         # browser itself to control, so that malicious browser client  
  170.         # code cannot spoof them and for instance pretend to be from a  
  171.         # different origin, etc..  
  172.         #  
  173.         # But if XmlHttpRequest forbids the browser client code from  
  174.         # setting these (as per the XmlHttpRequest spec), then they  
  175.         # are not author request headers. And if they are not author  
  176.         # request headers, then the browser should not include them in  
  177.         # the preflight request’s Access-Control-Request-Headers. And  
  178.         # if they are not included in Access-Control-Request-Headers,  
  179.         # then they should not be echoed by  
  180.         # Access-Control-Allow-Headers. And if they are not echoed by  
  181.         # Access-Control-Allow-Headers, then the browser should not  
  182.         # continue and execute actual request. So this seems to imply  
  183.         # that the CORS and XmlHttpRequest specs forbid certain  
  184.         # widely-used fields in CORS requests, including the Origin  
  185.         # field, which they also require for CORS requests.  
  186.         #  
  187.         # The bottom line: it seems there are headers needed for the  
  188.         # web and CORS to work, which at the moment you should  
  189.         # hard-code into Access-Control-Allow-Headers, although  
  190.         # official specs imply this should not be necessary.  
  191.         #   
  192.         add_header ‘Access-Control-Allow-Headers’ ‘Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since’;  
  193.   
  194.         # build entire response to the preflight request  
  195.         # no body in this response  
  196.         add_header ‘Content-Length’ 0;  
  197.         # (should not be necessary, but included for non-conforming browsers)  
  198.         add_header ‘Content-Type’ ‘text/plain charset=UTF-8’;  
  199.         # indicate successful return with no content  
  200.         return 204;  
  201.     }  
  202.     # –PUT YOUR REGULAR NGINX CODE HERE–  
  203. }  
  204.     
#




# A CORS (Cross-Origin Resouce Sharing) config for nginx # # == Purpose # # This nginx configuration enables CORS requests in the following way: # - enables CORS just for origins on a whitelist specified by a regular expression # - CORS preflight request (OPTIONS) are responded immediately # - Access-Control-Allow-Credentials=true for GET and POST requests # - Access-Control-Max-Age=20days, to minimize repetitive OPTIONS requests # - various superluous settings to accommodate nonconformant browsers # # == Comment on echoing Access-Control-Allow-Origin # # How do you allow CORS requests only from certain domains? The last # published W3C candidate recommendation states that the # Access-Control-Allow-Origin header can include a list of origins. # (See: http://www.w3.org/TR/2013/CR-cors-20130129/#access-control-allow-origin-response-header ) # However, browsers do not support this well and it likely will be # dropped from the spec (see, http://www.rfc-editor.org/errata_search.php?rfc=6454&eid=3249 ). # # The usual workaround is for the server to keep a whitelist of # acceptable origins (as a regular expression), match the request's # Origin header against the list, and echo back the matched value. # # (Yes you can use '*' to accept all origins but this is too open and # prevents using 'Access-Control-Allow-Credentials: true', which is # needed for HTTP Basic Access authentication.) # # == Comment on spec # # Comments below are all based on my reading of the CORS spec as of # 2013-Jan-29 ( http://www.w3.org/TR/2013/CR-cors-20130129/ ), the # XMLHttpRequest spec ( # http://www.w3.org/TR/2012/WD-XMLHttpRequest-20121206/ ), and # experimentation with latest versions of Firefox, Chrome, Safari at # that point in time. # # == Changelog # # shared at: https://gist.github.com/algal/5480916 # based on: https://gist.github.com/alexjs/4165271 # location / { # if the request included an Origin: header with an origin on the whitelist, # then it is some kind of CORS request. # specifically, this example allow CORS requests from # scheme : http or https # authority : any authority ending in “.mckinsey.com” # port : nothing, or : if ( h t t p o r i g i n   ( h t t p s ? : / / [ / ] \. m c k i n s e y \. c o m ( : [ 0 9 ] + ) ? ) ) { set cors “true”;    }    # Nginx doesn’t support nested If statements, so we use string    # concatenation to create a flag for compound conditions    # OPTIONS indicates a CORS pre-flight request    if ( request_method = ‘OPTIONS’) { set c o r s " {cors}options”; } # non-OPTIONS indicates a normal CORS request if ( r e q u e s t m e t h o d = G E T ) s e t $ c o r s " $ c o r s g e t ; i f ( request_method = ‘POST’) { set c o r s " {cors}post”; } # if it’s a GET or POST, set the standard CORS responses header if ( cors = “trueget”) {        # Tells the browser this origin may make cross-origin requests        # (Here, we echo the requesting origin, which matched the whitelist.)        add_header ‘Access-Control-Allow-Origin’ “$http_origin”;        # Tells the browser it may show the response, when XmlHttpRequest.withCredentials=true.        add_header ‘Access-Control-Allow-Credentials’ ‘true’;        # # Tell the browser which response headers the JS can see, besides the “simple response headers”        # add_header ‘Access-Control-Expose-Headers’ ‘myresponseheader’;    }    if ( cors = “truepost”) { # Tells the browser this origin may make cross-origin requests # (Here, we echo the requesting origin, which matched the whitelist.) add_header ‘Access-Control-Allow-Origin’ “ http_origin”;        # Tells the browser it may show the response, when XmlHttpRequest.withCredentials=true.        add_header ‘Access-Control-Allow-Credentials’ ‘true’;        # # Tell the browser which response headers the JS can see, besides the “simple response headers”        # add_header ‘Access-Control-Expose-Headers’ ‘myresponseheader’;    }    # if it’s OPTIONS, then it’s a CORS preflight request so respond immediately with no response body    if ( cors = “trueoptions”) { # Tells the browser this origin may make cross-origin requests # (Here, we echo the requesting origin, which matched the whitelist.) add_header ‘Access-Control-Allow-Origin’ “$http_origin”; # in a preflight response, tells browser the subsequent actual request can include user credentials (e.g., cookies) add_header ‘Access-Control-Allow-Credentials’ ‘true’; # # Return special preflight info # # Tell browser to cache this pre-flight info for 20 days add_header ‘Access-Control-Max-Age’ 1728000; # Tell browser we respond to GET,POST,OPTIONS in normal CORS requests. # # Not officially needed but still included to help non-conforming browsers. # # OPTIONS should not be needed here, since the field is used # to indicate methods allowed for “actual request” not the # preflight request. # # GET,POST also should not be needed, since the “simple # methods” GET,POST,HEAD are included by default. # # We should only need this header for non-simple requests # methods (e.g., DELETE), or custom request methods (e.g., XMODIFY) add_header ‘Access-Control-Allow-Methods’ ‘GET, POST, OPTIONS’; # Tell browser we accept these headers in the actual request # # A dynamic, wide-open config would just echo back all the headers # listed in the preflight request’s # Access-Control-Request-Headers. # # A dynamic, restrictive config, would just echo back the # subset of Access-Control-Request-Headers headers which are # allowed for this resource. # # This static, fairly open config just returns a hardcoded set of # headers that covers many cases, including some headers that # are officially unnecessary but actually needed to support # non-conforming browsers # # Comment on some particular headers below: # # Authorization – practically and officially needed to support # requests using HTTP Basic Access authentication. Browser JS # can use HTTP BA authentication with an XmlHttpRequest object # req by calling # # req.withCredentials=true, and # req.setRequestHeader(‘Authorization’,’Basic ’ + window.btoa(theusername + ‘:’ + thepassword)) # # Counterintuitively, the username and password fields on # XmlHttpRequest#open cannot be used to set the authorization # field automatically for CORS requests. # # Content-Type – this is a “simple header” only when it’s # value is either application/x-www-form-urlencoded, # multipart/form-data, or text/plain; and in that case it does # not officially need to be included. But, if your browser # code sets the content type as application/json, for example, # then that makes the header non-simple, and then your server # must declare that it allows the Content-Type header. # # Accept,Accept-Language,Content-Language – these are the # “simple headers” and they are officially never # required. Practically, possibly required. # # Origin – logically, should not need to be explicitly # required, since it’s implicitly required by all of # CORS. officially, it is unclear if it is required or # forbidden! practically, probably required by existing # browsers (Gecko does not request it but WebKit does, so # WebKit might choke if it’s not returned back). # # User-Agent,DNT – officially, should not be required, as # they cannot be set as “author request headers”. practically, # may be required. # # My Comment: # # The specs are contradictory, or else just confusing to me, # in how they describe certain headers as required by CORS but # forbidden by XmlHttpRequest. The CORS spec says the browser # is supposed to set Access-Control-Request-Headers to include # only “author request headers” (section 7.1.5). And then the # server is supposed to use Access-Control-Allow-Headers to # echo back the subset of those which is allowed, telling the # browser that it should not continue and perform the actual # request if it includes additional headers (section 7.1.5, # step 8). So this implies the browser client code must take # care to include all necessary headers as author request # headers. # # However, the spec for XmlHttpRequest#setRequestHeader # (section 4.6.2) provides a long list of headers which the # the browser client code is forbidden to set, including for # instance Origin, DNT (do not track), User-Agent, etc.. This # is understandable: these are all headers that we want the # browser itself to control, so that malicious browser client # code cannot spoof them and for instance pretend to be from a # different origin, etc.. # # But if XmlHttpRequest forbids the browser client code from # setting these (as per the XmlHttpRequest spec), then they # are not author request headers. And if they are not author # request headers, then the browser should not include them in # the preflight request’s Access-Control-Request-Headers. And # if they are not included in Access-Control-Request-Headers, # then they should not be echoed by # Access-Control-Allow-Headers. And if they are not echoed by # Access-Control-Allow-Headers, then the browser should not # continue and execute actual request. So this seems to imply # that the CORS and XmlHttpRequest specs forbid certain # widely-used fields in CORS requests, including the Origin # field, which they also require for CORS requests. # # The bottom line: it seems there are headers needed for the # web and CORS to work, which at the moment you should # hard-code into Access-Control-Allow-Headers, although # official specs imply this should not be necessary. # add_header ‘Access-Control-Allow-Headers’ ‘Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since’; # build entire response to the preflight request # no body in this response add_header ‘Content-Length’ 0; # (should not be necessary, but included for non-conforming browsers) add_header ‘Content-Type’ ‘text/plain charset=UTF-8’; # indicate successful return with no content return 204; } # –PUT YOUR REGULAR NGINX CODE HERE– }

服务器解析流程如下:

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

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

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

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

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

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

  1. location / {  
  2.   add_header Access-Control-Allow-Origin *;  
  3. }  
location / {
  add_header Access-Control-Allow-Origin *;
}

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

  1. <IfModule mod_setenvif.c>  
  2.     <IfModule mod_headers.c>  
  3.         <FilesMatch ”\.(cur|gif|ico|jpe?g|png|svgz?|webp)$”>  
  4.             SetEnvIf Origin ”:” IS_CORS  
  5.             Header set Access-Control-Allow-Origin ”*” env=IS_CORS  
  6.         </FilesMatch>  
  7.     </IfModule>  
  8. </IfModule>  
<IfModule mod_setenvif.c>
    <IfModule mod_headers.c>
        <FilesMatch "\.(cur|gif|ico|jpe?g|png|svgz?|webp)$">
            SetEnvIf Origin ":" IS_CORS
            Header set Access-Control-Allow-Origin "*" env=IS_CORS
        </FilesMatch>
    </IfModule>
</IfModule>

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

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

 

[javascript] view plain copy
print ?
  1. var img = new Image,  
  2.     canvas = document.createElement(”canvas”),  
  3.     ctx = canvas.getContext(”2d”),  
  4.     src = http://example.com/image; // insert image url here  
  5.   
  6. img.crossOrigin = ”Anonymous”;  
  7.   
  8. img.onload = function() {  
  9.     canvas.width = img.width;  
  10.     canvas.height = img.height;  
  11.     ctx.drawImage( img, 0, 0 );  
  12.     localStorage.setItem( ”savedImageData”, canvas.toDataURL(“image/png”) );  
  13. }  
  14. img.src = src;  
  15. // make sure the load event fires for cached images too  
  16. if ( img.complete || img.complete === undefined ) {  
  17.     img.src = ”data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==”;  
  18.     img.src = src;  
  19. }  
var img = new Image, 
canvas = document.createElement("canvas"),
ctx = canvas.getContext("2d"),
src = "http://example.com/image"; // insert image url here

img.crossOrigin = "Anonymous";

img.onload = function() {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage( img, 0, 0 );
localStorage.setItem( "savedImageData", canvas.toDataURL("image/png") );
}
img.src = src;
// make sure the load event fires for cached images too
if ( img.complete || img.complete === undefined ) {
img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
img.src = src;
}

上述配置完成后,重启服务器,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://blog.csdn.net/oyzl68/article/details/18741057

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

http://blog.csdn.net/freshlover/article/details/44223467


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

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

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

FireFox下的提示:

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

Canvas跨域Chrome下的提示:

UncaughtSecurityError:Failed to execute‘getImageData’ on ‘CanvasRenderingContext2D’:The canvas has been taintedby cross-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,

         //color: “#a9a9a7”,

         image2:”imgdata.php?url=http://js.xxx.com/static/activity/sq/guagua315/images/card_inner.jpg”,

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=newImage;

    img.onload=function(){

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

    }

    img.src=xi.responseText;

  }

}

PHP处理代码:

<?php//imgdata.php

 

  u r l = _GET[‘url’];

   i m g = f i l e g e t c o n t e n t s ( url);

  i m g n a m e = s u b s t r ( s t r r c h r ( url,“/”),1);

  file_put_contents( f n , 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。代码:

  1. #  
  2. # A CORS (Cross-Origin Resouce Sharing) config for nginx  
  3. #  
  4. # == Purpose  
  5. #  
  6. # This nginx configuration enables CORS requests in the following way:  
  7. # - enables CORS just for origins on a whitelist specified by a regular expression  
  8. # - CORS preflight request (OPTIONS) are responded immediately  
  9. # - Access-Control-Allow-Credentials=true for GET and POST requests  
  10. # - Access-Control-Max-Age=20days, to minimize repetitive OPTIONS requests  
  11. # - various superluous settings to accommodate nonconformant browsers  
  12. #  
  13. # == Comment on echoing Access-Control-Allow-Origin  
  14. #   
  15. # How do you allow CORS requests only from certain domains? The last  
  16. # published W3C candidate recommendation states that the  
  17. # Access-Control-Allow-Origin header can include a list of origins.  
  18. # (See: http://www.w3.org/TR/2013/CR-cors-20130129/#access-control-allow-origin-response-header )  
  19. # However, browsers do not support this well and it likely will be  
  20. # dropped from the spec (see, http://www.rfc-editor.org/errata_search.php?rfc=6454&eid=3249 ).  
  21. #   
  22. # The usual workaround is for the server to keep a whitelist of  
  23. # acceptable origins (as a regular expression), match the request’s  
  24. # Origin header against the list, and echo back the matched value.  
  25. #  
  26. # (Yes you can use ’*’ to accept all origins but this is too open and  
  27. # prevents using ‘Access-Control-Allow-Credentials: true’, which is  
  28. # needed for HTTP Basic Access authentication.)  
  29. #  
  30. # == Comment on  spec  
  31. #  
  32. # Comments below are all based on my reading of the CORS spec as of  
  33. # 2013-Jan-29 ( http://www.w3.org/TR/2013/CR-cors-20130129/ ), the  
  34. # XMLHttpRequest spec (  
  35. # http://www.w3.org/TR/2012/WD-XMLHttpRequest-20121206/ ), and  
  36. # experimentation with latest versions of Firefox, Chrome, Safari at  
  37. # that point in time.  
  38. #  
  39. # == Changelog  
  40. #  
  41. # shared at: https://gist.github.com/algal/5480916  
  42. # based on: https://gist.github.com/alexjs/4165271  
  43. #  
  44.   
  45. location / {  
  46.   
  47.     # if the request included an Origin: header with an origin on the whitelist,  
  48.     # then it is some kind of CORS request.  
  49.   
  50.     # specifically, this example allow CORS requests from  
  51.     #  scheme    : http or https  
  52.     #  authority : any authority ending in ”.mckinsey.com”  
  53.     #  port      : nothing, or :  
  54.     if ( http_origin&nbsp;~*&nbsp;(https?://[^/]*\.mckinsey\.com(:[0-9]+)?) ) {  
  55.         set  cors&nbsp;"true";&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;Nginx&nbsp;doesn't&nbsp;support&nbsp;nested&nbsp;If&nbsp;statements,&nbsp;so&nbsp;we&nbsp;use&nbsp;string&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;concatenation&nbsp;to&nbsp;create&nbsp;a&nbsp;flag&nbsp;for&nbsp;compound&nbsp;conditions&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;OPTIONS&nbsp;indicates&nbsp;a&nbsp;CORS&nbsp;pre-flight&nbsp;request&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;( request_method = ‘OPTIONS’) {  
  56.         set  cors&nbsp;" {cors}options”;    
  57.     }  
  58.   
  59.     # non-OPTIONS indicates a normal CORS request  
  60.     if ( request_method&nbsp;=&nbsp;'GET')&nbsp;{&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set&nbsp;$cors&nbsp;"${cors}get";&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;( request_method = ‘POST’) {  
  61.         set  cors&nbsp;" {cors}post”;  
  62.     }  
  63.   
  64.     # if it’s a GET or POST, set the standard CORS responses header  
  65.     if ( cors&nbsp;=&nbsp;"trueget")&nbsp;{&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;Tells&nbsp;the&nbsp;browser&nbsp;this&nbsp;origin&nbsp;may&nbsp;make&nbsp;cross-origin&nbsp;requests&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;(Here,&nbsp;we&nbsp;echo&nbsp;the&nbsp;requesting&nbsp;origin,&nbsp;which&nbsp;matched&nbsp;the&nbsp;whitelist.)&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add_header&nbsp;'Access-Control-Allow-Origin'&nbsp;"$http_origin";&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;Tells&nbsp;the&nbsp;browser&nbsp;it&nbsp;may&nbsp;show&nbsp;the&nbsp;response,&nbsp;when&nbsp;XmlHttpRequest.withCredentials=true.&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add_header&nbsp;'Access-Control-Allow-Credentials'&nbsp;'true';&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;#&nbsp;Tell&nbsp;the&nbsp;browser&nbsp;which&nbsp;response&nbsp;headers&nbsp;the&nbsp;JS&nbsp;can&nbsp;see,&nbsp;besides&nbsp;the&nbsp;"simple&nbsp;response&nbsp;headers"&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;add_header&nbsp;'Access-Control-Expose-Headers'&nbsp;'myresponseheader';&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;( cors = “truepost”) {  
  66.         # Tells the browser this origin may make cross-origin requests  
  67.         # (Here, we echo the requesting origin, which matched the whitelist.)  
  68.         add_header ‘Access-Control-Allow-Origin’ ” http_origin";&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;Tells&nbsp;the&nbsp;browser&nbsp;it&nbsp;may&nbsp;show&nbsp;the&nbsp;response,&nbsp;when&nbsp;XmlHttpRequest.withCredentials=true.&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add_header&nbsp;'Access-Control-Allow-Credentials'&nbsp;'true';&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;#&nbsp;Tell&nbsp;the&nbsp;browser&nbsp;which&nbsp;response&nbsp;headers&nbsp;the&nbsp;JS&nbsp;can&nbsp;see,&nbsp;besides&nbsp;the&nbsp;"simple&nbsp;response&nbsp;headers"&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;add_header&nbsp;'Access-Control-Expose-Headers'&nbsp;'myresponseheader';&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;if&nbsp;it's&nbsp;OPTIONS,&nbsp;then&nbsp;it's&nbsp;a&nbsp;CORS&nbsp;preflight&nbsp;request&nbsp;so&nbsp;respond&nbsp;immediately&nbsp;with&nbsp;no&nbsp;response&nbsp;body&nbsp;&nbsp;</span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;( cors = “trueoptions”) {  
  69.         # Tells the browser this origin may make cross-origin requests  
  70.         # (Here, we echo the requesting origin, which matched the whitelist.)  
  71.         add_header ‘Access-Control-Allow-Origin’ ”$http_origin”;  
  72.         # in a preflight response, tells browser the subsequent actual request can include user credentials (e.g., cookies)  
  73.         add_header ‘Access-Control-Allow-Credentials’ ‘true’;  
  74.   
  75.         #  
  76.         # Return special preflight info  
  77.         #  
  78.           
  79.         # Tell browser to cache this pre-flight info for 20 days  
  80.         add_header ‘Access-Control-Max-Age’ 1728000;  
  81.   
  82.         # Tell browser we respond to GET,POST,OPTIONS in normal CORS requests.  
  83.         #  
  84.         # Not officially needed but still included to help non-conforming browsers.  
  85.         #  
  86.         # OPTIONS should not be needed here, since the field is used  
  87.         # to indicate methods allowed for “actual request” not the  
  88.         # preflight request.  
  89.         #  
  90.         # GET,POST also should not be needed, since the “simple  
  91.         # methods” GET,POST,HEAD are included by default.  
  92.         #  
  93.         # We should only need this header for non-simple requests  
  94.         # methods (e.g., DELETE), or custom request methods (e.g., XMODIFY)  
  95.         add_header ‘Access-Control-Allow-Methods’ ‘GET, POST, OPTIONS’;  
  96.           
  97.         # Tell browser we accept these headers in the actual request  
  98.         #  
  99.         # A dynamic, wide-open config would just echo back all the headers  
  100.         # listed in the preflight request’s  
  101.         # Access-Control-Request-Headers.  
  102.         #  
  103.         # A dynamic, restrictive config, would just echo back the  
  104.         # subset of Access-Control-Request-Headers headers which are  
  105.         # allowed for this resource.  
  106.         #  
  107.         # This static, fairly open config just returns a hardcoded set of  
  108.         # headers that covers many cases, including some headers that  
  109.         # are officially unnecessary but actually needed to support  
  110.         # non-conforming browsers  
  111.         #   
  112.         # Comment on some particular headers below:  
  113.         #  
  114.         # Authorization – practically and officially needed to support  
  115.         # requests using HTTP Basic Access authentication. Browser JS  
  116.         # can use HTTP BA authentication with an XmlHttpRequest object  
  117.         # req by calling  
  118.         #   
  119.         #   req.withCredentials=true,  and  
  120.         #   req.setRequestHeader(‘Authorization’,’Basic ’ + window.btoa(theusername + ’:’ + thepassword))  
  121.         #  
  122.         # Counterintuitively, the username and password fields on  
  123.         # XmlHttpRequest#open cannot be used to set the authorization  
  124.         # field automatically for CORS requests.  
  125.         #  
  126.         # Content-Type – this is a “simple header” only when it’s  
  127.         # value is either application/x-www-form-urlencoded,  
  128.         # multipart/form-data, or text/plain; and in that case it does  
  129.         # not officially need to be included. But, if your browser  
  130.         # code sets the content type as application/json, for example,  
  131.         # then that makes the header non-simple, and then your server  
  132.         # must declare that it allows the Content-Type header.  
  133.         #   
  134.         # Accept,Accept-Language,Content-Language – these are the  
  135.         # “simple headers” and they are officially never  
  136.         # required. Practically, possibly required.  
  137.         #  
  138.         # Origin – logically, should not need to be explicitly  
  139.         # required, since it’s implicitly required by all of  
  140.         # CORS. officially, it is unclear if it is required or  
  141.         # forbidden! practically, probably required by existing  
  142.         # browsers (Gecko does not request it but WebKit does, so  
  143.         # WebKit might choke if it’s not returned back).  
  144.         #  
  145.         # User-Agent,DNT – officially, should not be required, as  
  146.         # they cannot be set as “author request headers”. practically,  
  147.         # may be required.  
  148.         #   
  149.         # My Comment:  
  150.         #  
  151.         # The specs are contradictory, or else just confusing to me,  
  152.         # in how they describe certain headers as required by CORS but  
  153.         # forbidden by XmlHttpRequest. The CORS spec says the browser  
  154.         # is supposed to set Access-Control-Request-Headers to include  
  155.         # only “author request headers” (section 7.1.5). And then the  
  156.         # server is supposed to use Access-Control-Allow-Headers to  
  157.         # echo back the subset of those which is allowed, telling the  
  158.         # browser that it should not continue and perform the actual  
  159.         # request if it includes additional headers (section 7.1.5,  
  160.         # step 8). So this implies the browser client code must take  
  161.         # care to include all necessary headers as author request  
  162.         # headers.  
  163.         #   
  164.         # However, the spec for XmlHttpRequest#setRequestHeader  
  165.         # (section 4.6.2) provides a long list of headers which the  
  166.         # the browser client code is forbidden to set, including for  
  167.         # instance Origin, DNT (do not track), User-Agent, etc.. This  
  168.         # is understandable: these are all headers that we want the  
  169.         # browser itself to control, so that malicious browser client  
  170.         # code cannot spoof them and for instance pretend to be from a  
  171.         # different origin, etc..  
  172.         #  
  173.         # But if XmlHttpRequest forbids the browser client code from  
  174.         # setting these (as per the XmlHttpRequest spec), then they  
  175.         # are not author request headers. And if they are not author  
  176.         # request headers, then the browser should not include them in  
  177.         # the preflight request’s Access-Control-Request-Headers. And  
  178.         # if they are not included in Access-Control-Request-Headers,  
  179.         # then they should not be echoed by  
  180.         # Access-Control-Allow-Headers. And if they are not echoed by  
  181.         # Access-Control-Allow-Headers, then the browser should not  
  182.         # continue and execute actual request. So this seems to imply  
  183.         # that the CORS and XmlHttpRequest specs forbid certain  
  184.         # widely-used fields in CORS requests, including the Origin  
  185.         # field, which they also require for CORS requests.  
  186.         #  
  187.         # The bottom line: it seems there are headers needed for the  
  188.         # web and CORS to work, which at the moment you should  
  189.         # hard-code into Access-Control-Allow-Headers, although  
  190.         # official specs imply this should not be necessary.  
  191.         #   
  192.         add_header ‘Access-Control-Allow-Headers’ ‘Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since’;  
  193.   
  194.         # build entire response to the preflight request  
  195.         # no body in this response  
  196.         add_header ‘Content-Length’ 0;  
  197.         # (should not be necessary, but included for non-conforming browsers)  
  198.         add_header ‘Content-Type’ ‘text/plain charset=UTF-8’;  
  199.         # indicate successful return with no content  
  200.         return 204;  
  201.     }  
  202.     # –PUT YOUR REGULAR NGINX CODE HERE–  
  203. }  
  204.     
#




猜你喜欢

转载自blog.csdn.net/qq_31001889/article/details/80507212