我正试图在一个现有的asp.net网站上启用CORS,该网站托管多个WCF服务。不幸的是,我很难让它发挥作用。乍一看,我被重定向到登录页面(该页面不存在),因此自定义身份验证服务生成的身份验证cookie可能有问题。
在继续之前,这里有一个关于我当前场景的简单描述:
- 我有一个网站A,它公开了几个web服务(除了认证服务只能由经过认证的用户访问),以及站点B,它有一个尝试与网络交互的页面服务
- 为了复制这个场景,我把services+html页面在同一个地方,我已经创建了一个别名(hosts文件)以模拟cors调用(假设我已经称之为outro.pt)
- 身份验证cookie是通过使用FormsAuthentication.GetAuthCookie,然后将其添加到通过调用response.AppendCookie方法进行响应
-
身份验证按预期工作:首先是OPTIONS调用,然后是POST呼叫当调用第二个web服务(再次POST)时,没有飞行前检查(因为第一个调用最终生成Access Control Max Age标头,以便缓存飞行前检查5分钟),但网站(outro.pt)最终返回了一个302将浏览器重定向到登录页面。
在继续之前,以下是用于处理飞行前和允许cors调用的演示代码(我已将其放在应用程序的beginrequest事件中):
private void Application_BeginRequest(object sender, EventArgs e) { var ctx = HttpContext.Current; //allow credentials: always ctx.Response.AddHeader("Access-Control-Allow-Credentials", "true"); //add allow origin header if (ctx.Request.Headers["Origin"] != null) { ctx.Response.AddHeader("Access-Control-Allow-Origin", ctx.Request.Headers["Origin"]); } if (ctx.Request.Headers["Access-Control-Request-Headers"] != null) { ctx.Response.AddHeader("Access-Control-Allow-Headers", ctx.Request.Headers["Access-Control-Request-Headers"]); } if (ctx.Request.HttpMethod.ToUpper() == "OPTIONS" ) { ctx.Response.AddHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS"); //keep preflight info for 5 mins ctx.Response.AddHeader("Access-Control-Max-Age", (5 * 60).ToString()); ctx.Response.End(); return; } }
现在,这里是生成身份验证cookie的演示代码(由于这是演示代码,我选择使用一个简单的通用处理程序:
public void ProcessRequest(HttpContext context) {
context.Response.ContentType = "application/json";
var name = "";
using (var reader = new StreamReader(context.Request.InputStream)) {
var std = (Student)JsonConvert.DeserializeObject(reader.ReadToEnd(),typeof(Student));
name = std == null ? "" : std.name;
}
if (!String.IsNullOrEmpty(name)) {
var cookie = FormsAuthentication.GetAuthCookie(name, false);
cookie.Domain = "outro.pt";
context.Response.AppendCookie(cookie);
context.Response.Write(JsonConvert.SerializeObject(new {valid = true}));
}
else {
context.Response.Write(JsonConvert.SerializeObject(new { valid = false }));
}
}
现在,在使用fiddler之后,我可以看到在调用验证处理程序时确实返回了cookie。例如,下面是一个通过调用上一个身份验证处理程序创建的cookie的示例:
设置Cookie:.ASPXAUTH=1CB7EF39DBA39BDA2FD2AA0AAFDAB67821A286D04F1678C89CFD6036094A3F9C36D2C9E48FFE35B95C8A742F553138A889CE63259F6DDC7A4D59868AF8A3F50EC037F1DAB73827B5D906A115C28FC8E4B744D661AF77592955F525E236D;domain=outro.pt;路径=/;HttpOnly
乍一看,我看不出这个身份验证cookie有什么问题(我认为它与正确的域相关联,每当我点击outro.pt内的任何页面时都应该发送它,对吧?-即使它被放在另一个asp.net应用程序中,比如outro.pt/demo/webservice.ashx?)
由于我在尝试访问第二个web服务时被重定向到登录页面,我认为问题是没有发送身份验证cookie。这是正确的:根据fiddler的说法,第二次调用的请求标头中没有发送cookie。我试了好几种方法,但都没能成功。
在阅读了这些文档后,我认为将withCredentials字段设置为true是我发送cookie唯一需要做的事情,对吧?顺便说一句,这是使用jquery2:执行的第二个web服务调用
var complete = url + "studentservice.ashx";
payload = {
url: complete,
type: 'POST',
xhrFields: {
withCredentials: true
},
contentType: 'application/json',
crossDomain: true,
dataType: 'json'
};
$.ajax(payload)
.done(function (data, status, xhr) {
alert("success");
})
.fail(function (xhr, status, error) {
alert("error" + error);
});
那么,当需要访问的web服务需要asp.net身份验证时,有人能使用cors吗?我错过了什么?
谢谢。
我想我发现了问题:用于验证用户(并生成cookie)的$.ajax方法调用没有withCredentials字段,所以从服务器返回的cookie最终被丢弃。