在我们日常的项目开发时使用AJAX,传统的Ajax请求只能获取在同一个域名下面的资源,但是HTML5打破了这个限制,允许Ajax发起跨域的请求。浏览器是可以发起跨域请求的,比如你可以外链一个外域的图片或者脚本。但是Javascript脚本是不能获取这些资源的内容的,它只能被浏览器执行或渲染。主要原因还是出于安全考虑,浏览器会限制脚本中发起的跨站请求。(同源策略, 即JavaScript或Cookie只能访问同域下的内容)。跨域的解决方案有多重JSONP、Flash、Iframe等,当然还有CORS(跨域资源共享,Cross-Origin Resource Sharing)今天就来了解下CORS的原理,以及如何使用。

一、CORS概述

跨源资源共享标准通过新增一系列 HTTP 头,让服务器能声明那些来源可以通过浏览器访问该服务器上的各类资源(包括CSS、图片、JavaScript 脚本以及其它类资源)。另外,对那些会对服务器数据造成破坏性影响的 HTTP 请求方法(特别是 GET 以外的 HTTP 方法,或者搭配某些MIME类型的POST请求),标准强烈要求浏览器必须先以 OPTIONS 请求方式发送一个预请求(preflight request),从而获知服务器端对跨源请求所支持 HTTP 方法。在确认服务器允许该跨源请求的情况下,以实际的 HTTP 请求方法发送那个真正的请求。服务器端也可以通知客户端,是不是需要随同请求一起发送信用信息(包括 Cookies 和 HTTP 认证相关数据)。

二、CORS原理

例如:域名A(http://a.example)的某 Web 应用程序中通过<img>标签引入了域名B(http://b.foo)站点的某图片资源(http://b.foo/image.jpg)。这就是一个跨域请求,请求http报头包含Origin: http://a.example,如果返回的http报头包含响应头 Access-Control-Allow-Origin: http://a.example (或者Access-Control-Allow-Origin: http://a.example),表示域名B接受域名B下的请求,那么这个图片就运行被加载。否则表示拒绝接受请求。

三、CORS跨域请求控制方法

1.http请求头

Origin: 普通的HTTP请求也会带有,在CORS中专门作为Origin信息供后端比对,表明来源域。

Access-Control-Request-Method: 接下来请求的方法,例如PUT, DELETE等等

Access-Control-Request-Headers: 自定义的头部,所有用setRequestHeader方法设置的头部都将会以逗号隔开的形式包含在这个头中

2.http响应头

然后浏览器再根据服务器的返回值判断是否发送非简单请求。简单请求前面讲过是直接发送,只是多加一个origin字段表明跨域请求的来源。然后服务器处理完请求之后,会再返回结果中加上如下控制字段

Access-Control-Allow-Origin: 允许跨域访问的域,可以是一个域的列表,也可以是通配符"*"。这里要注意Origin规则只对域名有效,并不会对子目录有效。即http://foo.example/subdir/ 是无效的。但是不同子域名需要分开设置,这里的规则可以参照同源策略

Access-Control-Allow-Credentials: 是否允许请求带有验证信息,XMLHttpRequest请求的withCredentials标志设置为true时,认证通过,浏览器才将数据给脚本程序。

Access-Control-Expose-Headers: 允许脚本访问的返回头,请求成功后,脚本可以在XMLHttpRequest中访问这些头的信息

Access-Control-Max-Age: 缓存此次请求的秒数。在这个时间范围内,所有同类型的请求都将不再发送预检请求而是直接使用此次返回的头作为判断依据,非常有用,大幅优化请求次数

Access-Control-Allow-Methods: 允许使用的请求方法,以逗号隔开

Access-Control-Allow-Headers: 允许自定义的头部,以逗号隔开,大小写不敏感

四、浏览器支持情况

在大部分现代浏览器中有所支持,支持(部分支持)CORS协议的浏览器有IE8+, Firefox5+, Chrome12+, Safari4+,移动端几乎全支持。

注:Internet Explorer 8 、9使用 XDomainRequest 对象实现CORS。

五、CORS使用案例

案例环境:客户端使用jQuery,服务端WebApi(2.2)。因本人使用.net语言,所以服务端就使用webApi来演示了。

首先新建一个webApi项目,这里就不截图一步步介绍了,然后使用Nuget安装支持cors的扩展组件,

Install-Package Microsoft.AspNet.WebApi.Cors

然后打开App_Start问价夹下的WebConfig.cs配置文件类,在Register方法中配置一个全局的cors,为了方便我将一些参数配置到web.config配置文件中

    <add key="cors_allowOrigins" value="*"/>
<add key="cors_allowHeaders" value="*"/>
<add key="cors_allowMethods" value="*"/>

CORS WebConfig 配置

            var allowOrigins = ConfigurationManager.AppSettings["cors_allowOrigins"];
var allowHeaders = ConfigurationManager.AppSettings["cors_allowHeaders"];
var allowMethods = ConfigurationManager.AppSettings["cors_allowMethods"];
var globalCors = new EnableCorsAttribute(allowOrigins, allowHeaders, allowMethods);
config.EnableCors(globalCors);

CORS 配置及启用

如果不想使用全局的CORS,可以在某个方法或者ApiController上这样配置:[EnableCors(origins: "*", headers: "*", methods: "*")],可以使用具体的参数,多个参数以逗号分隔,不用说,肯定英文逗号。origins 域名要带上http的顶级域名。需要添加 using System.Web.Http.Cors;

一般请求来说,客户端的AJAX请求不需要做任何改变,只需要服务端稍作改变即可。

客户端js代码:     apiRootPath是我预先设置的api的顶级域名。

$.ajax({
url: apiRootPath + "api/Account/Register",
type: "post",
data: {
"UserName": mobile,
"Password": pwd
},
dataType: "json",
success: function (data) {
if (data.State == true) {
RegSuccess(mobile, pwd);
} else {
$("#errorText").html(data.Message);
$("#registerBtn").text("注册");
}
}
});

因为我配置了全局的CORS方法,而且服务端没有特别之处了,和普通的网站(不跨越)写法一致,这里就不予贴出了。

如果需要对请求进行身份验证,怎么办?我们一cookies实现这个验证。

$.ajax({
url: apiRootPath + "api/Account/Login",
type: "post",
data: {
"UserName": userName,
"Password": password
},
crossDomain: true,
xhrFields: {
withCredentials: true
},
dataType: "json",
success: function (data) {
if (data.State == true) {
MLogin(userName, password);
} else {
$("#loginBtn").text("登录");
$("#errorText").html(data.Message);
}
}
});

注意这个两句话:crossDomain: true,xhrFields: {withCredentials: true}

六:安全隐患

如果程序猿偷懒将Access-Control-Allow-Origin设置为:Access-Control-Allow-Origin: * 允许任何来自任意域的跨域请求,那么久存在被 DDoS攻击的可能。

and待补充。。。

七、如有不足,欢迎指出并补充。

转载请注明出处,谢谢。

跨域的另一种解决方案——CORS(Cross-Origin Resource Sharing)跨域资源共享的更多相关文章

  1. 跨域的另一种解决方案CORS(CrossOrigin Resource Sharing)跨域资源共享

    在我们日常的项目开发时使用AJAX,传统的Ajax请求只能获取在同一个域名下面的资源,但是HTML5打破了这个限制,允许Ajax发起跨域的请求.浏览器是可以发起跨域请求的,比如你可以外链一个外域的图片 ...

  2. (转)跨域的另一种解决方案——CORS(Cross-Origin Resource Sharing)跨域资源共享

    在我们日常的项目开发时使用AJAX,传统的Ajax请求只能获取在同一个域名下面的资源,但是HTML5打破了这个限制,允许Ajax发起跨域的请求.浏览器是可以发起跨域请求的,比如你可以外链一个外域的图片 ...

  3. Node.js 【CORS(cross origin resource sharing) on ExpressJS之笔记】

    app.use(function(req, res, next) { res.header("Access-Control-Allow-Origin", "*" ...

  4. CORS (Cross Origin Resources Share) 跨域

    CORS 跨域 1 什么是跨域问题 基于安全考虑,浏览器会限制使用脚本发起任何跨域请求. 所谓的跨域请求,就是与当前页面的 http/ip/port 不一样的请求. 但在实际运用中,跨域获取数据的需求 ...

  5. spring 跨域 CORS (Cross Origin Resources Share) 跨域

    Spring提供了三种方式跨域 1.CorsFilter 过滤器 2.<mvc:cors> Bean(全局,推荐使用) 3.@CrossOrigin注解 以上三种方式本质都是用来配置Cor ...

  6. 【转】解决ajax跨域问题的5种解决方案

    转自: https://blog.csdn.net/itcats_cn/article/details/82318092   什么是跨域问题?跨域问题来源于JavaScript的"同源策略& ...

  7. 解决ajax跨域问题【5种解决方案】

    什么是跨域问题?跨域问题来源于JavaScript的"同源策略",即只有 协议+主机名+端口号 (如存在)相同,则允许相互访问.也就是说JavaScript只能访问和操作自己域下的 ...

  8. 跨域两种解决方案CORS以及JSONP

    一.CORS设置请求头 设置请求头实现跨域: //跨域的浏览器会让请求带Origin头,表明来自哪里的跨域请求 Origin: http://xxx.example //表明允许跨域访问 Access ...

  9. ajax跨域问题(三种解决方案)

    为什么会出现跨域 跨域问题来源于JavaScript的同源策略,即只有 协议+主机名+端口号 (如存在)相同,则允许相互访问.也就是说JavaScript只能访问和操作自己域下的资源,不能访问和操作其 ...

随机推荐

  1. WebApi系列~FromUri参数自动解析成实体的要求

    回到目录 关于webapi我之前写了一些文章,大家可以根据目录去浏览,今天要说的是个怪问题,也是被我忽略的一个问题,当你的Url参数需要被Api自动解析成实体的属性,实事上是要有条件的,不是所以属性都 ...

  2. 使用 jQuery & CSS3 制作美丽的照片画廊

    在本教程中,我们将创建一个很好看的照片画廊效果.我们的想法是,以显示专辑作为一个滑块,而当这张专辑被选中,我们将使用一个美丽的照片堆栈展示专辑的图像.在照片堆栈视图,我们可以通过将最上面的图像移动到所 ...

  3. jQuery实现鼠标经过图片变亮效果

    在线体验效果:http://hovertree.com/texiao/jquery/1.htm 以下是完整源代码: <!DOCTYPE html PUBLIC "-//W3C//DTD ...

  4. SQL多表查询

    设置主键:点击右键设为主键,在默认值那设置newid(),即可自动生成 Join inner join(内连接):select * from 表1 inner join 表2 on 表1.列 = 表2 ...

  5. 浅谈HTML5单页面架构(三)—— 回归本真:自定义路由 + requirejs + zepto + underscore

    本文转载自:http://www.cnblogs.com/kenkofox/p/4650310.html 不过,这一篇,我想进一步探讨一下这两个框架的优缺点,另外,再进一步,抛开这两个框架,回到本真, ...

  6. iOS crash 追终 ,iOS 如何定位crash 位置

    https://developer.apple.com/library/ios/technotes/tn2151/_index.html 错误分析是基于设备中的crash log 与 编译文件时生成的 ...

  7. python之import子目录文件

    问题:   在pre_tab.py文件下: print("AA") from test.te import login1 login1() from test.te import ...

  8. MongoDB安装及配置成服务

    最近接收了个新项目,这个项目用到了很多之前没用过的(MongoDB.Redis.MVC5+EF6 等等),以前只是看过别人用,自己从未尝试,唯独用了MVC2+EF4,可能是我落伍了,不扯了,进入正题. ...

  9. C++ 重载、重写、重定义

    出自:http://blog.163.com/clevertanglei900@126/blog/ 1 成员函数重载特征: a 相同的范围(在同一个类中) b 函数名字相同 c 参数不同 d virt ...

  10. mysql配置以及性能优化(转)

    MySQL配置文件my.cnf中文详解,附mysql性能优化方法分享 ================================================================= ...