您的位置:首页 > 编程语言 > ASP

ASP.NET跨域请求中的问题【CORS】

2016-09-12 13:47 609 查看
浏览器的安全策略会阻止网页向另一个站点发送ajax请求,同时也会阻止恶意站点从另一个站点读取数据。这种限制被称作“同源策略”。然而有时我们需要从一个站点访问另一个站点,比如从一个站点访问你的WebApi接口。

跨域资源共享-Cross Origin Resource Sharing(CORS)是一项W3C标准,允许服务端释放同源策略,使得服务端在接受一些跨域请求的同时拒绝其他的跨域请求。相比较早期的JSONP等技术而言,CORS更加安全更加灵活。

1.什么是“跨域”?

如果两个URL的协议、域名、端口相同,那么这两个URL就是同源。不是同源的就是跨域的,也就是说凡是发送请求URL的协议、域名、端口三者中任意一个与当前页面的URL不同即为跨域。

下面两个URL是同源的:

http://example.com/page1.html

http://example.com/page2.html

下面的URL和上面两个都不是同源的,也即是跨域的

URL说明
http://example.net不同的域名
http://example.com:9080/page1.html不同的端口
https://example.com/page1.html不同的协议
http://www.example.com/page1.html不同的子域名
注意:IE在比较是否同源时不考虑端口号

2.CORS如何工作

CORS特性提供了多个Http请求头以供跨域请求使用。如果一个浏览器支持CORS,它会自动的为跨域请求加上相应的http请求头,并不需要在javaScript中添加额外代码。

下面是一个跨域请求的示例,在Http请求头的“Origin”项中是发起请求的站点域名。

GET http://myservice.net/api/test HTTP/1.1

Referer: http://myclient.net/

Accept: * / *

Accept-Language: en-US

Origin: http://myclient.net

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)

Host: myservice.net

如果服务端允许了这个跨域请求,它会在http的Response的头部设置项Access-Control-Allow-Origin。只有当Response中Access-Control-Allow-Origin的值与Request中Origin的值相匹配时,这个请求才会成功。如果Access-Control-Allow-Origin的值是”*”,则意味着任意跨域访问都是被允许的。

HTTP/1.1 200 OK

Cache-Control: no-cache

Pragma: no-cache

Content-Type: text/plain; charset=utf-8

Access-Control-Allow-Origin: http://myclient.net

Date: Wed, 05 Jun 2013 06:27:30 GMT

Content-Length: 17

如果在HttpResponse的头部中没有包含Access-Control-Allow-Origin项,跨域请求会失败。即使服务端已经返回了正确的反馈,浏览器也不会将这个返回传递给客户端应用。

No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://myclient.net’ is therefore not allowed access. The response had HTTP status code 500.

对于一些CORS请求,浏览器会在发送实际需要的请求之前发送一个额外的请求,我们称之为“前置请求”。前置请求使用了Http Options方法,它包含了两个特殊的请求头Access-Control-Request-Method和Access-Control-Request-Headers。

OPTIONS http://myservice.net/api/test HTTP/1.1

Accept: * / *

Origin: http://myclient.net

Access-Control-Request-Method: PUT

Access-Control-Request-Headers: accept, x-my-custom-header

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)

Host: myservice.net

Content-Length: 0

也就是说浏览器发送了两次请求,首先发送前置请求,验证当前发送请求的站点是否在允许访问的域的范围内,若验证通过就发送真正的请求获取数据,否则请求就会被拒绝。在浏览器的调试界面(F12-Network)我们也可以看到请求是有两次。

在下列情况下,浏览器会跳过前置请求:

1.Http请求方法是GET、HEAD或POST

2.Http请求的Content-Type是application/x-www-form-urlencoded、multipart/form-data、text/plain

3.Http请求头包含了Accept, Accept-Language, Content-Language, Content-Type

3.如何使用CORS

在ASP.NET应用中,可以使用NuGet获取多个关于CORS的类库:



这些类库分别位于Owin和AspNet命名空间下,是CORS标准的不同实现,最终实现的效果是一样的,只是使用环境和方式不太一样。

3.1为WebApi添加CORS

通过NuGet安装Microsoft.AspNet.WebApi.Cors为WebApi添加CORS。使用[EnableCros]属性可以全局设置CORS,也可以为Controller或Action单独设置CORS。

全局(Global)设置

public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.EnableCors();
}
}


Controller设置

[EnableCors]
public class ValuesController : ApiController
{
public HttpResponseMessage Post() { ... }
[DisableCors]
public HttpResponseMessage PutItem(int id) { ... }
}


Action设置

public class ValuesController : ApiController
{
public HttpResponseMessage Post() { ... }

[EnableCors]

public HttpResponseMessage PutItem(int id) { ... }
}


其中[EnableCros]属性有多个项可以设置,可以实现指定的站点才允许跨域访问:[EnableCros(origin:”“,headers:”“,methods:”*”)]

3.2通过Owin实现CORS

Owin是微软推广的.NET Web应用程序与Web服务器之间的接口,通过Owin实现CORS需要使用NuGet安装Microsoft.Owin.Cros。在项目中添加Owin的Startup类:

public partial class Startup
{
public void Configuration(IAppBuilder app)
{
//允许跨域访问
app.UseCors(CorsOptions.AllowAll);
}
}


或者在web.config的system.webServer项下添加:

<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*"/>
<add name="Access-Control-Allow-Headers" value="*"/>
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE"/>
</customHeaders>
</httpProtocol>


对于WebApi或MVC,如果已经引用并实现了Owin中的CROS,就不需要在WebApiConfig中设置config.EnableCros()了。

3.3.其他实现CORS的方式

除了在代码和配置文件中添加CORS外,还可以在网站发布后通过修改IIS配置来实现CORS

打开IIS管理器,找到你的站点中的“HTTP响应标头”:



添加HTTP响应标头:

Access-Control-Allow-Credentials:true

Access-Control-Allow-Headers:origin,x-requested-with,content-type

Access-Control-Allow-Methods:POST,GET,OPTIONS

Access-Control-Allow-Origin:*

注意:如果应用程序包含上述两种以上情况时,只需在一处设置CORS,否则访问应用时会出错(Access-Control-Allow-Origin的值只能有一个):

Response to preflight request doesn’t pass access control check:The ‘Access-Control-Allow-Origin’ header contains multiple values ‘http://myclient.net,*’,but only one is allowed. Origin ‘http://myclient.net’ is therefore not allowed access.

参考文章

Enabling Cross-Origin Requests in ASP.NET Web API 2
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  asp.net CROS