WebApi 跨域问题解决方案:CORS

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiaouncle/article/details/84172466

前两篇文章介绍了WebApi项目的创建测试,今天来说说WebApi跨域访问的问题。本篇主要介绍了利用CORS解决跨域问题一些细节和具体步骤,下面来看看吧。

一、发布WebApi

既然是解决WebApi跨域问题,那WebApi(http://localhost:9002)和网站(http://localhost:57447)当然是单独部署了,只有这样WebApi服务和网站的域名才会不同,要不怎么出现垮域哇,主要代码如下:

[RoutePrefix("api/prefix")]
public class PleasureController : ApiController
{
    [Route("Pleasure/GetOne/{age:int=16}")]
    [HttpGet]
    public IEnumerable<string> GetOne(int age)
    {
        return new string[] { "GetOne(int age)->value1", "GetOne(int age)->value2" };
    }

    [HttpGet]
    public string GetOne(int id, string name, int age)
    {
        return string.Format("GetOne(int id, string name, int age)->id={0},name={1},age={2}", id, name, age);
    }

    [HttpGet]
    public string GetList()
    {
        return "GetList()->value";
    }
}

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API 路由
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional },
            constraints: new { id = @"\d*" }
        );

        config.Routes.MapHttpRoute(
            name: "ActionApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

二、不做跨域处理进行请求

有了WebApi服务,现在我们新建一个网站项目,并在前台请求http://localhost:9002/api/Pleasure/GetOne/5?name=aa&age=12,看看是否会成功。

function invoke1() {
    $.ajax({
        type: "get",
        url: "http://localhost:9002/api/Pleasure/GetOne/5",
        contentType: "application/json",
        data: "name=aaa&age=12",
        dataType: "json",
        success: function (data) {
            $("#result").val(data);
        },
        error: function (data) {

        }
    });
}

三、CORS解决跨域问题的原理 

CORS全称Cross-Origin Resource Sharing,中文全称跨域资源共享,是一种允许当前域的资源被其他域的脚本请求访问的机制。它解决跨域问题的原理是通过向http的请求报文和响应报文里面加入相应的标识告诉浏览器它能访问哪些域名的请求。比如我们向响应报文里面增加这个Access-Control-Allow-Origin:http://localhost:57447,就表示支持http://localhost:57447里面的所有请求访问系统资源。

四、CORS解决跨域问题的步骤 

1、WebApi项目设置

既然是设置资源能被哪些域名访问,那当然是在WebApi项目中设置了,如果是在自己的网站里设置可以访问哪些服务,怎么会有安全可言?

2、设置WebApiConfig.cs

三个*表示本服务支持任意请求来访问,实际中除了完全开放的服务,其他项目肯定不能这么干。到此为止跨域问题就已经解决了。

public static void Register(HttpConfiguration config)
{
    //跨域配置
    config.EnableCors(new EnableCorsAttribute("*", "*", "*"));

    // Web API 路由
    config.MapHttpAttributeRoutes();

    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional },
        constraints: new { id = @"\d*" }
    );

    config.Routes.MapHttpRoute(
        name: "ActionApi",
        routeTemplate: "api/{controller}/{action}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
}

3、在网站中再次访问WebApi

此时再次出发按钮的点击事件,就能正常获取到结果了。

并不是所有的浏览器都支持CORS来解决跨域问题,如下图所示IE8、IE9需要进行单独处理,必须在调用处指定 jQuery.support.cors = true;。至于网上说的CORS对IE8、9的解决方案XDomainRequest是怎么回事,本文不做探讨。

jQuery.support.cors = true;
function invoke1() {
    $.ajax({
        type: "get",
        url: "http://localhost:9002/api/Pleasure/GetOne/5",
        contentType: "application/json",
        data: "name=aaa&age=12",
        dataType: "json",
        success: function (data) {
            $("#result").val(data);
        },
        error: function (data) {

        }
    });
}

4、设置跨域参数

第二步中使用的是config.EnableCors(new EnableCorsAttribute("*", "*", "*"));这样是很不安全的,现在设置为只允许某域名能访问

public static void Register(HttpConfiguration config)
{
    //跨域配置
    config.EnableCors(new EnableCorsAttribute("http://localhost:57447", "*", "*"));
    //config.EnableCors(new EnableCorsAttribute("http://localhost:57777,http://localhost:57447", "*", "*"));

    // Web API 路由
    config.MapHttpAttributeRoutes();

    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional },
        constraints: new { id = @"\d*" }
    );

    config.Routes.MapHttpRoute(
        name: "ActionApi",
        routeTemplate: "api/{controller}/{action}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
}

若允许多个域名访问WebApi,可用逗号隔开,示例代码如下:

public static void Register(HttpConfiguration config)
{
    //跨域配置
    config.EnableCors(new EnableCorsAttribute("http://localhost:57777,http://localhost:57447", "*", "*"));

    ......
}

5、通过配置文件设置跨域参数

如果在代码中把跨域参数写死那每次想改配置就必须改代码,这很不方便,我们不如将跨域参数放到配置文件中,这样需要变动的时候只改配置文件即可。


 

五、细粒度设置支持跨域 

如果只想让某个方法支持跨域访问的话,可以利用EnableCors特性来实现,EnableCors特性可以加到控制器、方法上,示例如下:

public class PleasureController : ApiController
{
    [Route("Pleasure/GetOne/{age:int=16}")]
    [HttpGet]
    public IEnumerable<string> GetOne(int age)
    {
        return new string[] { "GetOne(int age)->value1", "GetOne(int age)->value2" };
    }

    [EnableCors(origins: "http://localhost:57447", headers: "*", methods: "*")]
    [HttpGet]
    public string GetOne(int id, string name, int age)
    {
        return string.Format("GetOne(int id, string name, int age)->id={0},name={1},age={2}", id, name, age);
    }

    [HttpGet]
    public string GetList()
    {
        return "GetList()->value";
    }
}

感谢:
感谢懒得安分老哥分享的内容http://www.cnblogs.com/landeanfen/p/5177176.html

猜你喜欢

转载自blog.csdn.net/xiaouncle/article/details/84172466