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

浏览器的安全策略会阻止网页向另一个站点发送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

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值