美文网首页
【跨域】解决办法:利用 Access-Control-Allow

【跨域】解决办法:利用 Access-Control-Allow

作者: 以他齐 | 来源:发表于2018-10-23 09:58 被阅读0次

    【跨域】解决办法:利用 Access-Control-Allow-Origin

    传统的跨域请求没有好的解决方案,无非就是jsonp和iframe,随着跨域请求的应用越来越多,W3C提供了跨域请求的标准方案(Cross-Origin Resource Sharing)。IE8、Firefox 3.5 及其以后的版本、Chrome浏览器、Safari 4 等已经实现了 Cross-Origin Resource Sharing 规范,实现了跨域请求。

    在服务器响应客户端的时候,带上Access-Control-Allow-Origin头信息。

    Access-Control-Allow-Origin 所有域名设置:

    Access-Control-Allow-Origin:*#则允许所有域名的脚本访问该资源。

    Access-Control-Allow-Origin 单个域名设置:

    Access-Control-Allow-Origin:https://www.fujieace.com    #允许特定的域名访问。

    Access-control-Allow-Origin 多个域名设置:

    很多人认为直接按照以下这样写就可以了,其实是错误的,因为Access-Control-Allow-Origin只允许一个值;逗号分隔多个值是行不通的。

    Access-Control-Allow-Origin: https://www.google.com,https://www.baidu.com

    于是换种方式,查资料得到一个这样的思路:先自己判断域名是否是允许的,如果是再设置允许跨域访问。那么这样就可以了。Node.js多域名跨域代码如下:

    app.all(‘*’,function(req, res, next){if( req.headers.origin == ‘https://www.google.com’ || req.headers.origin == ‘https://www.baidu.com’ ){ res.header(“Access-Control-Allow-Origin”, req.headers.origin); res.header(‘Access-Control-Allow-Methods’, ‘POST, GET’); res.header(‘Access-Control-Allow-Headers’, ‘X-Requested-With’); res.header(‘Access-Control-Allow-Headers’, ‘Content-Type’); } next(); });

    使用时可以把允许访问的域名写成一个数组,然后JS写一个比较字符串是否在数组内的函数,这样使用就比较方便了。其中:

    Access-Control-Allow-Origin 就是我们需要设置的域名。

    Access-Control-Allow-Methods 是允许的请求方式。

    Access-Control-Allow-Headers 跨域允许包含的头。

    PHP跨塔例子,只需PHP添加响应头信息:

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

    Cross-Origin Resource Sharing协议介绍

    传统的Ajax请求只能获取在同一个域名下面的资源,但是HTML5打破了这个限制,允许Ajax发起跨域的请求。浏览器是可以发起跨域请求的,比如你可以外链一个外域的图片或者脚本。但是Javascript脚本是不能获取这些资源的内容的,它只能被浏览器执行或渲染。

    在Flash和Silverlight中,服务器需要创建一个crossdomain.xml的文件来允许跨域请求。如果这个文件声明“http://your.site”允许来自“http://my.site”的请求,则来自“http://my.site”的请求可以访问所有“http://your.site”的文件。这是一种整个站点层面上的控制模式,要么你允许一个外域的站点访问,要么拒绝。

    COR不一样,它是页面层次的控制模式。每一个页面需要返回一个名为‘Access-Control-Allow-Origin’的HTTP头来允许外域的站点访问。你可以仅仅暴露有限的资源和有限的外域站点访问。在COR模式中,访问控制的职责可以放到页面开发者的手中,而不是服务器管理员。当然页面开发者需要写专门的处理代码来允许被外域访问。

    另外一个主要的区别是,某个站点的crossdomain.xml文件是最早被浏览器获取并分析的。如果一个外域的站点不允许被访问,浏览器压根就不会发出跨域请求。

    COR则相反,Javascript先发出跨域请求,然后检查回复的‘Access-Control-Allow-Origin’头。如果这个头允许该外域访问,则Javascript可以读取这个回复,否则就被禁止访问。如果请求不是一个简单的COR,则向外域服务器发送预检验请求,如果回复的头部允许访问,则发送跨域请求,否则禁止。

    COR的实现标准就是CORS协议。

    对于浏览器来说,COR请求都是Javascript发起的,COR请求有两种:

    1、简单的COR请求,它可以直接向外域资源发起请求。它必须仅仅包含简单的方法和头,具体定义看[2] 6.1。

    2、如果COR包含复杂的方法和头,它需要发出预检验(Preflight)请求,它先向资源服务器发出一个OPTIONS方法、包含“Origin”头的请求。该回复可以控制COR请求的方法,HTTP头以及验证等信息。只有该请求获得允许以后,才会发起真实的外域请求。

    下面是一个简单的COR请求:

    varclient =newXMLHttpRequest();client.open("GET","http://bar.org/b")client.onreadystatechange =function(){/* do something */}client.send()

    假设这个请求所在页面的域是“http://foo.org”。 如果来自“http://bar.org/b”的回复包含这样的头:

    Access-Control-Allow-Origin: http://foo.org

    则表明,它允许来自“http://foo.org”的跨域请求。

    下面的Javascript会发出预检验请求和真实请求:

    varclient =newXMLHttpRequest();client.open("GET","http://bar.org/b")client.setRequestHeader('Content-Type','text/html')client.onreadystatechange =function(){/* do something */}client.send()

    由于“Content-type: text/html”不是一个简单的头,它会先向"http://bar.org/b"发出一个OPTIONS的HTTP请求。 回复可能包含这样的头:

    Access-Control-Allow-Origin: http://foo.orgAccess-Control-Max-Age: 3628800Access-Control-Allow-Methods: GET,PUT,DELETEAccess-Control-Allow-Headers:content-type"Access-Control-Allow-Origin"表明它允许"http://foo.org"发起跨域请求"Access-Control-Max-Age"表明在3628800秒内,不需要再发送预检验请求,可以缓存该结果"Access-Control-Allow-Methods"表明它允许GET、PUT、DELETE的外域请求"Access-Control-Allow-Headers"表明它允许跨域请求包含content-type头

    如果预检验请求获得通过,接下来Javascript就会发起真实的COR请求,过程跟简单的COR请求类似。

    CORS协议的实现

    现在HTML5的标准如火如荼的在制定和发展中,CORS作为HTML5的一部分,在大部分现代浏览器中有所支持,支持(部分支持)CORS协议的浏览器有IE8+, Firefox5+, Chrome12+, Safari4+

    服务端实现

    Thinktecture.IdentityModel 这个库已经为我们的WebAPI,MVC的项目做好了支持,具体参看[6]。

    参考资料:

    [1] 、http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity

    [2] 、http://www.w3.org/TR/cors/

    [3]、https://en.wikipedia.org/wiki/Cross-origin_resource_sharing

    [4]、http://www.cnblogs.com/yoyiorlee/archive/2010/11/07/1871308.html

    [5]、http://restfulobjects.codeplex.com/wikipage?title=Cross%20Origin%20Resource%20Sharing&referringTitle=Documentation

    [6]、https://brockallen.com/2012/06/28/cors-support-in-webapi-mvc-and-iis-with-thinktecture-identitymodel/

    相关文章

      网友评论

          本文标题:【跨域】解决办法:利用 Access-Control-Allow

          本文链接:https://www.haomeiwen.com/subject/xheozftx.html