5

我有一个 C# SOAP Web 服务以及一些IHTTPHandler部署到https://localhost:123. 我有一个关于http://localhost尝试使用 jQuery 向其中一个处理程序发送 AJAX POST 请求的 HTML 页面。我每次都得到以下信息:

XMLHttpRequest 无法加载https://localhost:123/(S(the_session_id))/MyHandler.ashx。Access-Control-Allow- Originhttp://localhost不允许 Origin。

我已经尝试像在这个问题CrossOriginModule中那样创建一个模块和处理程序,按照他们的建议更新我的 web.config。我已经尝试添加到我的处理程序中,正如这个问题中所建议的那样。我尝试按照此博客文章中有关在web.config 中添加到/的步骤进行操作。没有什么帮助。CrossOriginHandlercontext.Response.AppendHeader("Access-Control-Allow-Headers", "x-requested-with");ProcessRequestOPTIONSSimpleHandlerFactory-Integrated-4.0system.webServerhandlers

这是我的处理程序ProcessRequest

    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "application/json";
        context.Response.AppendHeader("Access-Control-Allow-Origin", "*");
        context.Response.AppendHeader("Access-Control-Allow-Headers", "x-requested-with");
        context.Response.Write( /* some JSON string */ );
    }

这是我的 web.config 的相关部分:

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="Access-Control-Allow-Origin" value="*" />
    </customHeaders>
  </httpProtocol>
  <modules runAllManagedModulesForAllRequests="true">
    <add name="CrossOriginModule" preCondition="managedHandler" type="MyNamespace.CrossOriginModule, MyNamespace, Version=1.0.0.0, Culture=neutral" />
  </modules>
  <handlers>
    <add name="CrossOrigin" verb="OPTIONS" path="*" type="MyNamespace.CrossOriginHandler, MyNamespace, Version=1.0.0.0, Culture=neutral" />
    <remove name="SimpleHandlerFactory-Integrated-4.0" />
    <add name="SimpleHandlerFactory-Integrated-4.0" path="*.ashx" verb="GET,HEAD,POST,DEBUG,OPTIONS" type="System.Web.UI.SimpleHandlerFactory" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" />
    <add name="MyHandler" verb="*" path="MyHandler.ashx" type="MyNamespace.MyHandler, MyNamespace, Version=1.0.0.0, Culture=neutral" />
  </handlers>
</system.webServer>

使用 jQuery 1.7.2,这是我向我的处理程序发出请求的方式:

$.ajax({
    url: url,
    data: {user: userName, pass: password},
    type: 'POST',
    dataType: 'json',
    success: function(data, textStatus, jqXHR) {
        ...
    }
});

我也没有在服务器上的会话中使用 cookie,所以<sessionState cookieless="true" />在我的 web.config 中,如果这很重要的话。我的服务器是 IIS 7.5。

我可以对大多数请求使用 JSONP,因为我没有在 URL 中传递敏感数据。但是,对于这个处理程序,我需要进行常规 POST,因为它涉及发送纯文本密码。它通过 SSL,但这篇文章建议即使通过 SSL,也不要在 URL 中传递敏感数据。所以我需要通过 AJAX 向 https URL 发出 POST 请求并返回 JSON,并且请求页面不会与服务器位于同一主机上。

编辑:我尝试过的其他一些事情:

更改我的 web.confighttpProtocol部分:

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Methods" value="OPTIONS,POST,GET"/>
    <add name="Access-Control-Allow-Headers" value="x-requested-with"/>
    <add name="Access-Control-Allow-Origin" value="*" /><!-- Also tried http://localhost -->
  </customHeaders>
</httpProtocol>

我添加context.Response.AppendHeader("Access-Control-Allow-Methods", "POST");ProcessRequest. 我还尝试context.Response.AppendHeader("Access-Control-Allow-Methods", "POST,OPTIONS");将我的 jQueryajax选项更改为 include contentType: 'application/json',这导致它发出 OPTIONS 请求而不是 POST ——这仍然失败。

我应该IHTTPHandler在 web.config 中列出我的所有自定义类<handlers>吗?我MyHandler现在有它verb="*",但它似乎没有帮助。

编辑:所以有些奇怪。根据我的日志输出,当我发布到服务器端时,看起来我的请求实际上是在服务器端进行的,但是浏览器的行为就像它被拒绝了一样,仍然告诉我“不允许原始本地主机”。因此,我向服务器发送的 AJAX POST 像我希望的那样对我进行了身份验证,但是浏览器取消了请求,并且 Chrome 控制台中显示了一个错误,因此我的success事件处理程序不会触发。

4

2 回答 2

3

您的处理程序的 ProcessRequest 还应设置以下标头:

Access-Control-Allow-Methods: POST

(基本上,此标头应与 Access-Control-Allow-Headers 响应标头一起设置在 OPTIONS 响应中)。

于 2012-06-28T12:55:59.270 回答
1

这很愚蠢,我不确定发生了什么,但我的 POST 正在通过,我的身份验证正在服务器上进行,但浏览器认为它是不允许的,所以它失败了。我已经有一个支持 JSONP 的处理程序,它将判断会话是否仍处于活动状态并且用户已通过身份验证,因此我将 AJAX 调用更改为以下内容:

$.ajax({
    url: url,
    data: {user: userName, pass: password},
    type: 'POST',
    dataType: 'json',
    complete: function(jqXHR, textStatus) {
        checkIfAuthenticated(
            function() { // authenticated
                onComplete(true, null)
            },
            function() { // not authenticated
                onComplete(false, textStatus);
            }
        );
    }
});

所以我的Chrome 控制台中仍然显示“XMLHttpRequest cannot load https://.../AuthHandler.ashx. Origin is not allowed by Access-Control-Allow-Origin”错误,Chrome 中的“网络”选项卡仍将 POST 请求显示为已取消。http://localhost我最终不得不在这里通过该checkIfAuthenticated函数发出一个额外的请求,以查看身份验证是否失败,但它确实有效。

ProcessRequest在服务器上的MyHandler样子是这样的:

public void ProcessRequest(HttpContext context)
{
    context.Response.ClearHeaders();
    string origin = context.Request.Headers["Origin"];
    context.Response.AppendHeader("Access-Control-Allow-Origin",
        string.IsNullOrEmpty(origin) ? "*" : origin);
    string requestHeaders = context.Request.Headers["Access-Control-Request-Headers"];
    context.Response.AppendHeader("Access-Control-Allow-Headers",
        string.IsNullOrEmpty(requestHeaders) ? "*" : requestHeaders);
    context.Response.AppendHeader("Access-Control-Allow-Methods", "POST, OPTIONS");
    context.Response.ContentType = "application/json";
    context.Response.Write(/* JSON response */);
    context.Response.Flush();
}

这是我的 web.config 的相关部分最终的样子:

  <system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Methods" value="OPTIONS,POST,GET"/>
        <add name="Access-Control-Allow-Headers" value="x-requested-with"/>
        <add name="Access-Control-Allow-Origin" value="*" />
      </customHeaders>
    </httpProtocol>
    <handlers>
      <add name="MyHandler" verb="*" path="MyHandler.ashx" type="MyNamespace.MyHandler, MyNamespace, Version=1.0.0.0, Culture=neutral" />
    </handlers>
  </system.webServer>

我更喜欢让我的浏览器相信该请求确实被允许的解决方案,因为这是一个愚蠢的解决方法。

于 2012-06-28T16:08:29.423 回答