我有一个C#SOAP Web服务以及部署到IHTTPHandler
的一些自定义https://localhost:123
类。我在http://localhost
上有一个HTML页面,试图使用jQuery向其中一个处理程序发送一个AJAX POST请求。我每次都得到以下内容:
XMLHttpRequest无法加载
https://localhost:123/(S(the_session_id))/MyHandler.ashx
。 Access-Control-Allow-Origin不允许原点http://localhost
。
我尝试在this question中创建CrossOriginModule
模块和CrossOriginHandler
处理程序,按照他们的建议更新我的web.config。我已尝试将context.Response.AppendHeader("Access-Control-Allow-Headers", "x-requested-with");
添加到我的处理程序的ProcessRequest
,如this question中所述。我尝试按照this blog post中有关在web.config中OPTIONS
/ SimpleHandlerFactory-Integrated-4.0
中将system.webServer
添加到handlers
的步骤进行操作。什么都没有帮助。
这是我的处理程序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,但this post建议不要通过SSL传递URL中的敏感数据。所以我需要通过AJAX向https URL发出POST请求并返回JSON,并且请求页面不会与服务器位于同一主机上。
编辑:我尝试过的其他一些事情:
更改我的web.config httpProtocol
部分:
<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");
并更改了我的jQuery ajax
选项以包含contentType: 'application/json'
,这导致它发出OPTIONS请求而不是POST - 这仍然失败。
我是否应该在IHTTPHandler
的web.config中列出我的所有自定义<handlers>
类?我现在MyHandler
有verb="*"
,但它似乎没有帮助。
编辑:所以有些进一步的陌生感。根据我的日志记录输出,看起来我的请求实际上是在服务器端进行的,但是浏览器的行为就像它被拒绝了,仍然告诉我'origin localhost不允许'。所以我对服务器的AJAX POST就像我希望的那样对我进行身份验证,但是浏览器会取消请求并且Chrome控制台中会显示错误,因此我的success
事件处理程序不会触发。
答案 0 :(得分:3)
你的处理程序的ProcessRequest也应该设置以下标题:
Access-Control-Allow-Methods: POST
(基本上,应在OPTIONS响应中设置此标头,以及Access-Control-Allow-Headers响应标头。)
答案 1 :(得分:0)
这是愚蠢的,我不确定发生了什么,但是我的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);
}
);
}
});
所以我仍然有一个“XMLHttpRequest无法加载https://.../AuthHandler.ashx
。我的Chrome控制台中显示的Access-Control-Allow-Origin不允许来源http://localhost
”和Chrome中的“网络”标签仍显示POST请求已取消。我最终必须通过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>
我更倾向于使用我的浏览器说服该请求确实被允许的解决方案,因为这是一个愚蠢的解决方法。