【问题标题】:Support OPTIONS request header in aspx page在 aspx 页面中支持 OPTIONS 请求头
【发布时间】:2011-09-29 03:04:48
【问题描述】:

我正在维护一个接受表单发布的服务,并在添加对 CORS 请求的支持时遇到了 Firefox 3.6 中的问题,它发送带有 OPTIONS 请求标头的预检请求。

我在使用通用 http 处理程序页面添加必要的 Access-Control-Allow-Origin 响应标头时没有遇到任何问题,但我在使用完整的 aspx 页面时遇到了困难。它绝对没有达到 Page_Load,我无法弄清楚它在页面生命周期的哪个位置卡住了。

有人有什么想法吗?

谢谢!

【问题讨论】:

  • 不确定您的意思,因为 Web 服务没有页面加载事件。通常,Web 服务只是具有 webmethod 属性的单个函数。 msdn.microsoft.com/en-us/library/…
  • 对不起,“服务”的使用令人困惑。这是一个带有接受 POST 的页面的网站。我知道它不需要是一个 aspx 页面,但有些页面已经链接到它,所以它不能轻易更改。

标签: c# .net asp.net ajax webforms


【解决方案1】:

您可以使用HttpModuleHttpHandler 来做到这一点

我认为其中一些来自某处的文章,而其他部分是内部开发的......所以如果其中一些来自其他地方,我提前道歉,因为没有给予应有的信任:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace YourNamespaceHere
{
    using System;
    using System.Web; 
    using System.Collections;

    public class CrossOriginModule : IHttpModule {
        public String ModuleName {
            get { return "CrossOriginModule"; } 
        }    

        public void Init(HttpApplication application) {
            application.BeginRequest += (new EventHandler(this.Application_BeginRequest));
        }

        private void Application_BeginRequest(Object source, EventArgs e) {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;
            CrossOriginHandler.SetAllowCrossSiteRequestOrigin(context);
        }

        public void Dispose() 
        {
        }
    }

   public class CrossOriginHandler : IHttpHandler
    {
        #region IHttpHandler Members
        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
            //Clear the response (just in case)
            ClearResponse(context);

            //Checking the method
            switch (context.Request.HttpMethod.ToUpper())
            {
                //Cross-Origin preflight request
                case "OPTIONS":
                    //Set allowed method and headers
                    SetAllowCrossSiteRequestHeaders(context);
                    //Set allowed origin
                    //This happens for us with our module:
                    SetAllowCrossSiteRequestOrigin(context);
                    //End
                    context.Response.End();
                    break;

                default:
                    context.Response.Headers.Add("Allow", "OPTIONS");
                    context.Response.StatusCode = 405;
                    break;
            }

            context.ApplicationInstance.CompleteRequest();
        }
        #endregion

        #region Methods
        protected void ClearResponse(HttpContext context)
        {
            context.Response.ClearHeaders();
            context.Response.ClearContent();
            context.Response.Clear();
        }

        protected void SetNoCacheHeaders(HttpContext context)
        {
            context.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
            context.Response.Cache.SetValidUntilExpires(false);
            context.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
            context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            context.Response.Cache.SetNoStore();
        }
        #endregion

        public static void SetAllowCrossSiteRequestHeaders(HttpContext context)
        {
            string requestMethod = context.Request.Headers["Access-Control-Request-Method"];

            context.Response.AppendHeader("Access-Control-Allow-Methods", "GET,POST");

            //We allow any custom headers
            string requestHeaders = context.Request.Headers["Access-Control-Request-Headers"];
            if (!String.IsNullOrEmpty(requestHeaders))
                context.Response.AppendHeader("Access-Control-Allow-Headers", requestHeaders);
        }

        public static void SetAllowCrossSiteRequestOrigin(HttpContext context)
        {
            string origin = context.Request.Headers["Origin"];
            if (!String.IsNullOrEmpty(origin))
                context.Response.AppendHeader("Access-Control-Allow-Origin", origin);
            else
                //This is necessary for Chrome/Safari actual request
                context.Response.AppendHeader("Access-Control-Allow-Origin", "*");
        }
    }
}

在 Web.config 中:

  ...
  <system.webServer>
     ...
     <modules runAllManagedModulesForAllRequests="true">
     ...
           <add name="CrossOriginModule" preCondition="managedHandler" type="YOURNANMESPACEHERE.CrossOriginModule, ASSEMBLYNAME" />
    </modules>
    <handlers>
           <add name="CrossOrigin" verb="OPTIONS" path="*" type="YOURNAMESPACEHERE.CrossOriginHandler, ASSEMBLYNAME" />
    </handlers>
  </system.webServer>

【讨论】:

  • 这是我一直在寻找的解决方案。我的前端不允许使用 *(星号)或多个地址的 Access-Control-Allow-Origin 来回答。此外,预检 OPTION 请求中也需要标头。此解决方案将 Access-Control-Allow-Origin 标头与所有 http 请求中的 Origin 标头中发送的值添加到响应中。
【解决方案2】:

Steve 的回答令人惊叹,它不可避免地让我找到了解决方案,这就是我投赞成票的原因。但是,在我看来,HttpHandler 可能不是明确需要的。所以我配置了 CORS,严格在模块本身中插入请求管道。我的代码:

using System;
using System.Web;

namespace NAMESPACE.HttpModules
{
    public class CrossOriginModule : IHttpModule
    {
        public String ModuleName
        {
            get { return "CrossOriginModule"; }
        }

        public void Init(HttpApplication application)
        {
            application.BeginRequest += (new EventHandler(this.Application_BeginRequest));
        }

        private void Application_BeginRequest(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            string httpMethod = context.Request.HttpMethod.ToUpper();

            //preflight
            if (httpMethod == "OPTIONS")
            {
                ClearResponse(context);

                //Set allowed method and headers
                SetAllowCrossSiteRequestHeaders(context);
                //Set allowed origin
                SetAllowCrossSiteRequestOrigin(context);

                //end request
                context.ApplicationInstance.CompleteRequest();
            }
            else
            {
                SetAllowCrossSiteRequestOrigin(context);
            }

        }
        static void SetAllowCrossSiteRequestHeaders(HttpContext context)
        {
            string requestMethod = context.Request.Headers["Access-Control-Request-Method"];

            context.Response.AppendHeader("Access-Control-Allow-Methods", "GET,POST");

            //We allow any custom headers
            string requestHeaders = context.Request.Headers["Access-Control-Request-Headers"];
            if (!String.IsNullOrEmpty(requestHeaders))
                context.Response.AppendHeader("Access-Control-Allow-Headers", requestHeaders);

            //allow credentials
            context.Response.AppendHeader("Access-Control-Allow-Credentials", "true");
        }

        static void SetAllowCrossSiteRequestOrigin(HttpContext context)
        {
            string origin = context.Request.Headers["Origin"];
            if (!String.IsNullOrEmpty(origin))
                context.Response.AppendHeader("Access-Control-Allow-Origin", origin);
            else
                context.Response.AppendHeader("Access-Control-Allow-Origin", "*");
        }

        static void ClearResponse(HttpContext context)
        {
            context.Response.ClearHeaders();
            context.Response.ClearContent();
            context.Response.Clear();
        }

        public void Dispose()
        {
        }
    }

}

在你的web.config

<modules runAllManagedModulesForAllRequests="true">
    <add name="CrossOriginModule" preCondition="managedHandler" type="NAMESPACE.HttpModules.CrossOriginModule" />
</modules>

这将根据需要配置响应标头,并让 MVC 像往常一样处理请求。

【讨论】:

    【解决方案3】:

    确保您的 web.config 中有以下内容,并按照我的回答(几乎没有代码)https://stackoverflow.com/a/62583142/2411916

    <configuration>
      <system.webServer>
        <modules runAllManagedModulesForAllRequests="true"/>
      </system.webServer>
    </configuration>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-03
      • 2014-05-13
      • 1970-01-01
      • 2019-07-13
      • 2014-08-12
      • 2016-07-17
      • 2011-09-10
      • 2015-06-13
      相关资源
      最近更新 更多