博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WebApi跨域
阅读量:4347 次
发布时间:2019-06-07

本文共 8852 字,大约阅读时间需要 29 分钟。

一、跨域问题的由来

 

 

同源策略:出于安全考虑,浏览器会限制脚本中发起的跨站请求,浏览器要求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的跨域问题。

api接口地址:http://127.0.0.1:8004/api/Values/ResturnResult

[HttpGet]public string ResturnResult(){      return "Success";}

从web站点发送请求:

$(function () {        $.ajax({            type: "get",            url: "http://127.0.0.1:8004/api/Values/ResturnResult",            data: {},            success: function (data, status) {                if (status == "success") {                    $("#result").html(data);                }            },            error: function (e) {                $("#result").html("Error");            },            complete: function () {            }        });    });

结果:

四、跨域问题解决方案

1、使用CORS跨域(始终会报错,暂时还没有找到解决方案)

在WebApi项目上面使用Nuget搜索“microsoft.aspnet.webapi.cors”,安装

代码如下:

//WebApiConfig中代码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 }            );        }    }//脚本$.ajax({            type: "get",            url: "http://localhost:8004/api/Charging/GetAllChargingData",            data: { _type: 1 },            success: function (data, status) {                if (status == "success") {                    $("#div_test").html(data);                }            },            error: function (e) {                $("#div_test").html("Error");            },            complete: function () {            }        });//webapipublic class ChargingController : ApiController    {        ///         /// 得到所有数据        ///         /// 
返回数据
[HttpGet] public string GetAllChargingData() { return "Success"; } }

运行webapi始终报错:(如果您知道解决方案,请指点,多谢!)

2、通过配置文件配置;在IE10之下不可以;

 

3、扩展api:

///     /// Cors特性    ///     [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]    public class CorsAttribute : Attribute    {        public Uri[] AllowOrigins { get; private set; }        public string ErrorMessage { get; private set; }        public CorsAttribute(params string[] allowOrigins)        {            this.AllowOrigins = (allowOrigins ?? new string[0]).Select(origin => new Uri(origin)).ToArray();        }        public bool TryEvaluate(HttpRequestMessage request, out IDictionary
headers) { headers = null; string origin = null; try { origin = request.Headers.GetValues("Origin").FirstOrDefault(); } catch (Exception) { this.ErrorMessage = "Cross-origin request denied"; return false; } Uri originUri = new Uri(origin); if (this.AllowOrigins.Contains(originUri)) { headers = this.GenerateResponseHeaders(request); return true; } this.ErrorMessage = "Cross-origin request denied"; return false; } private IDictionary
GenerateResponseHeaders(HttpRequestMessage request) { //设置响应头"Access-Control-Allow-Methods" string origin = request.Headers.GetValues("Origin").First(); Dictionary
headers = new Dictionary
(); headers.Add("Access-Control-Allow-Origin", origin); if (request.IsPreflightRequest()) { //设置响应头"Access-Control-Request-Headers" //和"Access-Control-Allow-Headers" headers.Add("Access-Control-Allow-Methods", "*"); string requestHeaders = request.Headers.GetValues("Access-Control-Request-Headers").FirstOrDefault(); if (!string.IsNullOrEmpty(requestHeaders)) { headers.Add("Access-Control-Allow-Headers", requestHeaders); } } return headers; } } ///
/// HttpRequestMessage扩展方法 /// public static class HttpRequestMessageExtensions { public static bool IsPreflightRequest(this HttpRequestMessage request) { return request.Method == HttpMethod.Options && request.Headers.GetValues("Origin").Any() && request.Headers.GetValues("Access-Control-Request-Method").Any(); } }

 

///     /// 跨域资源访问的HTTP处理程序    ///     public class CorsMessageHandler : DelegatingHandler    {        protected override Task
SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { //得到描述目标Action的HttpActionDescriptor HttpMethod originalMethod = request.Method; bool isPreflightRequest = request.IsPreflightRequest(); if (isPreflightRequest) { string method = request.Headers.GetValues("Access-Control-Request-Method").First(); request.Method = new HttpMethod(method); } HttpConfiguration configuration = request.GetConfiguration(); HttpControllerDescriptor controllerDescriptor = configuration.Services.GetHttpControllerSelector().SelectController(request); HttpControllerContext controllerContext = new HttpControllerContext(request.GetConfiguration(), request.GetRouteData(), request) { ControllerDescriptor = controllerDescriptor }; HttpActionDescriptor actionDescriptor = configuration.Services.GetActionSelector().SelectAction(controllerContext); //根据HttpActionDescriptor得到应用的CorsAttribute特性 CorsAttribute corsAttribute = actionDescriptor.GetCustomAttributes
().FirstOrDefault() ?? controllerDescriptor.GetCustomAttributes
().FirstOrDefault(); if (null == corsAttribute) { return base.SendAsync(request, cancellationToken); } //利用CorsAttribute实施授权并生成响应报头 IDictionary
headers; request.Method = originalMethod; bool authorized = corsAttribute.TryEvaluate(request, out headers); HttpResponseMessage response; if (isPreflightRequest) { if (authorized) { response = new HttpResponseMessage(HttpStatusCode.OK); } else { response = request.CreateErrorResponse(HttpStatusCode.BadRequest, corsAttribute.ErrorMessage); } } else { response = base.SendAsync(request, cancellationToken).Result; } //添加响应报头 if (headers != null && headers.Any()) foreach (var item in headers) response.Headers.Add(item.Key, item.Value); return Task.FromResult
(response); } }
GlobalConfiguration.Configuration.MessageHandlers.Add(new CorsMessageHandler());
IHttpActionResult的使用,需要安装 Microsoft.AspNet.WebApi;
[Cors("http://localhost:10154")]    public class ContactsController : ApiController    {        public IHttpActionResult GetAllContacts()        {            Contact[] contacts = new Contact[]             {                 new Contact{ Name="张三", PhoneNo="123", EmailAddress="zhangsan@gmail.com"},                 new Contact{ Name="李四", PhoneNo="456", EmailAddress="lisi@gmail.com"},                 new Contact{ Name="王五", PhoneNo="789", EmailAddress="wangwu@gmail.com"},             };            return Json
>(contacts); } } public class Contact { public string Name { get; set; } public string PhoneNo { get; set; } public string EmailAddress { get; set; } }

关于CORS详解,参见:http://www.cnblogs.com/artech/p/cors-4-asp-net-web-api-02.html

webapi系列文章:http://www.cnblogs.com/r01cn/tag/ASP.NET%20Web%20API/default.html?page=1

转载于:https://www.cnblogs.com/tianboblog/p/5448368.html

你可能感兴趣的文章
总结(6)--- python基础知识点小结(细全)
查看>>
亿级曝光品牌视频的幕后设定
查看>>
ARPA
查看>>
JSP开发模式
查看>>
我的Android进阶之旅------>Android嵌入图像InsetDrawable的使用方法
查看>>
Detours信息泄漏漏洞
查看>>
win32使用拖放文件
查看>>
Android 动态显示和隐藏软键盘
查看>>
raid5什么意思?怎样做raid5?raid5 几块硬盘?
查看>>
【转】how can i build fast
查看>>
null?对象?异常?到底应该如何返回错误信息
查看>>
django登录验证码操作
查看>>
(简单)华为Nova青春 WAS-AL00的USB调试模式在哪里开启的流程
查看>>
图论知识,博客
查看>>
[原创]一篇无关技术的小日记(仅作暂存)
查看>>
20145303刘俊谦 Exp7 网络欺诈技术防范
查看>>
原生和jQuery的ajax用法
查看>>
iOS开发播放文本
查看>>
20145202马超《java》实验5
查看>>
JQuery 事件
查看>>