• WebApi Ajax 跨域请求解决方法(CORS实现)


    640?wx_fmt=jpeg

    ASP.NET Web API 的好用使用过的都知道,没有复杂的配置文件,一个简单的ApiController加上需要的Action就能工作。但是在使用API的时候总会遇到跨域请求的问题,

    特别各种APP万花齐放的今天,API的跨域请求是不能避免的。


    在默认情况下,为了防止CSRF跨站的伪造攻击(或者是 javascript的同源策略(Same-Origin Policy)),一个网页从另外一个域获取数据时就会收到限制。有一些方法可以突破这个限制,那就是大家熟知的JSONP, 当然这只是众多解决方法中一种,由于JSONP只支持GET的请求,如今的复杂业务中已经不能满足需求。而CORS(Cross Origin Resource Sharing https://www.w3.org/wiki/CORS)跨域资源共享,是一种新的header规范,可以让服务器端放松跨域的限制,可以根据header来切换限制或者不限制跨域请求。重要的是它支持所有http请求方式。


    XMLHttpRequest 跨域 POST或GET请求 ,请求方式会自动变成OPTIONS的问题。

    由于CORS(cross origin resource share)规范的存在,浏览器会首先发送一次options嗅探,同时header带上origin,判断是否有跨域请求权限,服务器响应access control allow origin的值,供浏览器与origin匹配,如果匹配则正式发送post请求,即便是服务器允许程序跨域访问,若不支持 options 请求,请求也会死掉。

    浏览器为了安全起见,会Preflighted Request的透明服务器验证机制支持开发人员使用自定义的头部、GET或POST之外的方法,以及不同类型的主题内容,也就是会先发送一个 options 请求,

    问问服务器是否会正确(允许)请求,确保请求发送是安全的。


    出现 OPTIONS 的情况一般为:


    1、非GET 、POST请求

    2、POST请求的content-type不是常规的三个:application/x- www-form-urlencoded(使用 HTTP 的 POST 方法提交的表单)、multipart/form-data(同上,但主要用于表单提交时伴随文件上传的场合)、text/plain(纯文本) 

    3、POST请求的payload为text/html 

    4、设置自定义头部


    OPTIONS请求头部中会包含以下头部:Origin、Access-Control-Request-Method、Access-Control-Request-Headers,发送这个请求后,服务器可以设置如下头部与浏览器沟通来判断是否允许这个请求。

    Access-Control-Allow-Origin、Access-Control-Allow-Method、Access-Control-Allow-Headers

    方法一

    此方法功能强大,可以解决ASP.NET Web API复杂跨域请求,携带复杂头部信息,正文内容和授权验证信息


    public class CrosHandler:DelegatingHandler

    {

        private const string Origin = "Origin";

        private const string AccessControlRequestMethod = "Access-Control-Request-Method";

        private const string AccessControlRequestHeaders = "Access-Control-Request-Headers";

        private const string AccessControlAllowOrign = "Access-Control-Allow-Origin";

        private const string AccessControlAllowMethods = "Access-Control-Allow-Methods";

        private const string AccessControlAllowHeaders = "Access-Control-Allow-Headers";

        private const string AccessControlAllowCredentials = "Access-Control-Allow-Credentials";

        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)

        {

            bool isCrosRequest = request.Headers.Contains(Origin);

            bool isPrefilightRequest = request.Method == HttpMethod.Options;

            if (isCrosRequest)

            {

                Task<HttpResponseMessage> taskResult = null;

                if (isPrefilightRequest)

                {

                    taskResult = Task.Factory.StartNew<HttpResponseMessage>(() =>

                    {

                        HttpResponseMessage response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);

                        response.Headers.Add(AccessControlAllowOrign,

                            request.Headers.GetValues(Origin).FirstOrDefault());

                        string method = request.Headers.GetValues(AccessControlRequestMethod).FirstOrDefault();

                        if (method != null)

                        {

                            response.Headers.Add(AccessControlAllowMethods, method);

                        }

                        string headers = string.Join(", ", request.Headers.GetValues(AccessControlRequestHeaders));

                        if (!string.IsNullOrWhiteSpace(headers))

                        {

                            response.Headers.Add(AccessControlAllowHeaders, headers);

                        }

                        response.Headers.Add(AccessControlAllowCredentials, "true");

                        return response;

                    }, cancellationToken);

                }

                else

                {

                    taskResult = base.SendAsync(request, cancellationToken).ContinueWith<HttpResponseMessage>(t =>

                    {

                        var response = t.Result;

                        response.Headers.Add(AccessControlAllowOrign,

                            request.Headers.GetValues(Origin).FirstOrDefault());

                        response.Headers.Add(AccessControlAllowCredentials, "true");

                        return response;

                    });

                }

                return taskResult;

            }

            return base.SendAsync(request, cancellationToken);

        }

    }


    使用方式,在Global.asax文件添加

    protected void Application_Start()

    {

        IOCConfig.RegisterAll();

        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);

        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

        RouteConfig.RegisterRoutes(RouteTable.Routes);

        BundleConfig.RegisterBundles(BundleTable.Bundles);

        GlobalConfiguration.Configuration.MessageHandlers.Add(new CrosHandler());

    }


    方法二 

    配置文件中添加如下配置,此方法简单,应对简单的跨域请求

    <system.webServer>

        <httpProtocol>

          <customHeaders>

            <add name="Access-Control-Allow-Origin" value="*" />

            <add name="Access-Control-Allow-Headers" value="Content-Type" />

            <add name="Access-Control-Allow-Methods" value="GET, POST,OPTIONS" />

          </customHeaders>

        </httpProtocol>

    <system.webServer>

    640?wx_fmt=png


  • 相关阅读:
    java基础部分的一些有意思的东西。
    antdvue按需加载插件babelpluginimport报错
    阿超的烦恼 javaScript篇
    .NET E F(Entity Framework)框架 DataBase First 和 Code First 简单用法。
    JQuery获得input ID相同但是type不同的方法
    gridview的删除,修改,数据绑定处理
    jgGrid数据格式
    Cannot read configuration file due to insufficient permissions
    Invoke action which type of result is JsonResult on controller from view using Ajax or geJSon
    Entity model数据库连接
  • 原文地址:https://www.cnblogs.com/hgmyz/p/12352163.html
Copyright © 2020-2023  润新知