C#进阶系列——WebApi 跨域问题解决方案:CORS

摘要:
因为我们的WebApi和MVC是两个不同的项目,所以在它们运行时存在上述跨域问题。回到顶部3.跨域问题解决细节,我将使用一个简单的示例来说明如何使用CORS解决WebApi的跨域问题。WebApi项目负责提供界面服务,MVC项目负责页面呈现。Web和WebApiCORS的端口号分别为“27239”和“27221”。
 

正文

前言:上篇总结了下WebApi的接口测试工具的使用,这篇接着来看看WebAPI的另一个常见问题:跨域问题。本篇主要从实例的角度分享下CORS解决跨域问题一些细节。

WebApi系列文章

一、跨域问题的由来

同源策略:出于安全考虑,浏览器会限制脚本中发起的跨站请求,浏览器要求JavaScript或Cookie只能访问同域下的内容。

正是由于这个原因,我们不同项目之间的调用就会被浏览器阻止。比如我们最常见的场景:WebApi作为数据服务层,它是一个单独的项目,我们的MVC项目作为Web的显示层,这个时候我们的MVC里面就需要调用WebApi里面的接口取数据展现在页面上。因为我们的WebApi和MVC是两个不同的项目,所以运行起来之后就存在上面说的跨域的问题。

二、跨域问题解决原理

CORS全称Cross-Origin Resource Sharing,中文全称跨域资源共享。它解决跨域问题的原理是通过向http的请求报文和响应报文里面加入相应的标识告诉浏览器它能访问哪些域名的请求。比如我们向响应报文里面增加这个Access-Control-Allow-Origin:http://localhost:8081,就表示支持http://localhost:8081里面的所有请求访问系统资源。其他更多的应用我们就不一一列举,可以去网上找找。

三、跨域问题解决细节

 下面我就结合一个简单的实例来说明下如何使用CORS解决WebApi的跨域问题。

1、场景描述

我们新建两个项目,一个WebApi项目(下图中WebApiCORS),一个MVC项目(下图中Web)。WebApi项目负责提供接口服务,MVC项目负责页面呈现。如下:

C#进阶系列——WebApi 跨域问题解决方案:CORS第1张

其中,Web与WebApiCORS端口号分别为“27239”和“27221”。Web项目需要从WebApiCORSS项目里面取数据,很显然,两个项目端口不同,所以并不同源,如果使用常规的调用方法肯定存在一个跨域的问题。

简单介绍下测试代码,Web里面有一个HomeController

复制代码
   public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }
    }
复制代码

对应的Index.cshtml

复制代码
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <script src="http://t.zoukankan.com/~/Content/jquery-1.9.1.js"></script>
    <link href="http://t.zoukankan.com/~/Content/bootstrap/css/bootstrap.css" rel="stylesheet" />
    <script src="http://t.zoukankan.com/~/Content/bootstrap/js/bootstrap.js"></script>
    <script src="http://t.zoukankan.com/~/Scripts/Home/Index.js"></script>
</head>
<body>
    测试结果:<div id="div_test"> 

    </div>
</body>
</html>
复制代码

Index.js文件

复制代码
var ApiUrl = "http://localhost:27221/";
$(function () {
    $.ajax({
        type: "get",
        url: ApiUrl + "api/Charging/GetAllChargingData",
        data: {},
        success: function (data, status) {
            if (status == "success") {
                $("#div_test").html(data);
            }
        },
        error: function (e) {
            $("#div_test").html("Error");
        },
        complete: function () {

        }

    });
});
复制代码

WebApiCORS项目里面有一个测试的WebApi服务ChargingController

复制代码
  public class ChargingController : ApiController
    {
        /// <summary>
        /// 得到所有数据
        /// </summary>
        /// <returns>返回数据</returns>
        [HttpGet]
        public string GetAllChargingData()
        {
            return "Success";
        }
    }
复制代码

配置WebApi的路由规则为通过action调用。WebApiConfig.cs文件

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

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

2、场景测试

1)我们不做任何的处理,直接将两个项目运行起来。看效果如何

 IE浏览器:

C#进阶系列——WebApi 跨域问题解决方案:CORS第12张

谷歌浏览器:

C#进阶系列——WebApi 跨域问题解决方案:CORS第13张

这个结果另博主也很吃惊,不做任何跨域处理,IE10、IE11竟然可以直接请求数据成功,而同样的代码IE8、IE9、谷歌浏览器却不能跨域访问。此原因有待查找,应该是微软动了什么手脚。

2)使用CORS跨域

首先介绍下CORS如何使用,在WebApiCORS项目上面使用Nuget搜索“microsoft.aspnet.webapi.cors”,安装第一个

C#进阶系列——WebApi 跨域问题解决方案:CORS第14张

然后在App_Start文件夹下面的WebApiConfig.cs文件夹配置跨域

复制代码
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            //跨域配置
            config.EnableCors(new EnableCorsAttribute("*", "*", "*"));

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

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

我们暂定三个“*”号,当然,在项目中使用的时候一般需要指定对哪个域名可以跨域、跨域的操作有哪些等等。这个在下面介绍。

IE10、IE11

C#进阶系列——WebApi 跨域问题解决方案:CORS第17张

谷歌浏览器

C#进阶系列——WebApi 跨域问题解决方案:CORS第18张

IE8、IE9

C#进阶系列——WebApi 跨域问题解决方案:CORS第19张

这个时候又有新问题了,怎么回事呢?我都已经设置跨域了呀,怎么IE8、9还是不行呢?这个时候就有必要说说CORS的浏览器支持问题了。网上到处都能搜到这张图:

C#进阶系列——WebApi 跨域问题解决方案:CORS第20张

上图描述了CORS的浏览器支持情况,可以看到IE8、9是部分支持的。网上说的解决方案都是Internet Explorer 8 、9使用 XDomainRequest 对象实现CORS。是不是有这么复杂?于是博主各种百度寻找解决方案。最后发现在调用处指定 jQuery.support.cors = true; 这一句就能解决IE8、9的问题了。具体是在Index.js里面

复制代码
jQuery.support.cors = true;
var ApiUrl = "http://localhost:27221/";
$(function () {
    $.ajax({
        type: "get",
        url: ApiUrl + "api/Charging/GetAllChargingData",
        data: {},
        success: function (data, status) {
            if (status == "success") {
                $("#div_test").html(data);
            }
        },
        error: function (e) {
            $("#div_test").html("Error");
        },
        complete: function () {

        }
    });
});
复制代码

这句话的意思就是指定浏览器支持跨域。原来IE9以上版本的浏览器、谷歌、火狐等都默认支持跨域,而IE8、9却默认不支持跨域,需要我们指定一下。你可以在你的浏览器里面打印jQuery.support.cors看看。这样设置之后是否能解决问题呢?我们来看效果:

C#进阶系列——WebApi 跨域问题解决方案:CORS第23张

问题完美解决。至于网上说的CORS对IE8、9的解决方案XDomainRequest是怎么回事,有待实例验证。

3)CORS的具体参数设置。

上文我们使用

config.EnableCors(new EnableCorsAttribute("*", "*", "*"));

这一句解决了跨域问题,上面说了,这种*号是不安全的。因为它表示只要别人知道了你的请求url,任何请求都可以访问到你的资源。这是相当危险的。所以需要我们做一些配置,限制访问权限。比如我们比较常见的做法如下:

 配置方法一、在Web.Config里面(PS:这两张图源自:http://www.cnblogs.com/moretry/p/4154479.html

C#进阶系列——WebApi 跨域问题解决方案:CORS第24张

然后在WebApiConfig.cs文件的Register方法里面

C#进阶系列——WebApi 跨域问题解决方案:CORS第25张

配置方法二、如果你只想对某一些api做跨域,可以直接在API的类上面使用特性标注即可。

复制代码
  [EnableCors(origins: "http://localhost:8081/", headers: "*", methods: "GET,POST,PUT,DELETE")]
    public class ChargingController : ApiController
    {
        /// <summary>
        /// 得到所有数据
        /// </summary>
        /// <returns>返回数据</returns>
        [HttpGet]
        public string GetAllChargingData()
        {
            return "Success";
        }
    }
复制代码

 

免责声明:文章转载自《C#进阶系列——WebApi 跨域问题解决方案:CORS》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Windows SC命令详解pt-archiver归档数据丢失下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

log4net写入到SQL server的基本配置(downmoon)

log4net是一个开源的错误日志记录项目,易用性强,源自log4j,品质值得信赖。 下面汇报一下我的安装部署log4net到MS sql server的经验。 一、首先是下载log4net最新版 地址:http://logging.apache.org/log4net/ 直接引用dll也行,我是把下载的源码在Vs2005下编译成log4net.dll  ...

08 Tomcat+Java Web项目的创建和War的生成

1.web服务器软件:服务器:安装了服务器软件的计算机服务器软件:接收用户的请求,处理请求,做出响应 * web服务器软件:接收用户的请求,处理请求,做出响应。在web服务器软件中,可以部署web项目,让用户通过浏览器来访问这些项目 常见的java相关的web服务器软件:webLogic:oracle公司,大型的JavaEE服务器,支持所有的JavaEE规...

pywinauto客户端自动化---pywinauto初始

目前流行的自动化就是web,app,接口算是目前最主流的测试内容了,那么如果让做安装windows上的客户端自动化呢?是不是一脸懵?今天安静给大家介绍python的第三方库,可以帮助我们做客户端的自动化 pywinauto pywinauto是一组用于自动化Microsoft Windows GUI的python模块。 最简单的是,它允许您将鼠标和键盘操作...

特来电CMDB应用实践

        配置管理数据库(Configuration Management Database,以下简称CMDB)是一个老生常谈的话题,不同的人有不同的见解,实际应用时,因为企业成熟度以及软硬件规模不同,别人的成功经验很难直接复制,因此用好了会成为整个应用系统的基石,用不好就成了鸡肋。特来电云平台在规划伊始,便意识到了CMDB的重要性,在实践中不断丰富...

html5 如何打包成apk,将H5封装成android应用APK文件的几种方法

直接使用编程软件提供的方法: 1、需要下载安装MyEclipse2014,Android SDK,eclipse(需配置Android开发环境) Java和Android环境安装与配置。 2、打开MyEclipse2014,新建一个HTML5 Mobile Application Project,命名,例如:hello。 3、html5程序在工程www目...

WEB接口测试之Jmeter接口测试自动化 (二)(数据分离)

转载: http://www.cnblogs.com/chengtch/p/6105231.html 通过逐个录入的方式,好不容易将需要测试几十个接口的300多个测试用例录入sampler-http请求中,固定的测试环境跑起来也还 感觉良好。不料在新服务器环境中跑用例时,问题来了:修改参数维护脚本等成本太大! 脚本参数是写死的,修改起来得一个个请求打开来...