2013-08-29 46 views
4

我试图在一个现有的asp.net网站上启用CORS,该网站承载了几个WCF服务。不幸的是,我正在努力工作。乍一看,我被重定向到登录页面(不存在),所以可能是由自定义身份验证服务生成的身份验证cookie有问题。CORS:访问需要身份验证的Web服务

继续之前,这里是我当前场景的简单描述:

  • 我有站点A,暴露多个Web服务(所有,但 认证服务只能通过身份验证的用户访问), 和网站B,它有一个页面,试图与网络互动 服务
  • 为了复制这种情况下,我已经把 服务+ html页面放在同一个地方,我已经创建一个别名 (hosts文件),以模拟cors调用(比方说,我 称之为outro.pt)
  • 通过使用 的FormsAuthentication.GetAuthCookie产生的验证cookie,然后它通过调用Response.AppendCookie方法
  • 认证工作正常添加到 响应:首先有一个OPTIONS呼叫,然后是POST 呼叫;当第二个Web服务被调用(POST再次)时,没有 预检检查(因为第一次调用结束生成一个 访问控制最大年龄标头为了缓存预检检查为 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 }));  
     } 

    } 

现在,使用招后,我可以看到,该cookie被弄回来的时候验证处理程序被调用。举例来说,这里是通过调用创建到先前的认证处理一个的cookie的例子:

的Set-Cookie:.ASPXAUTH = 1CB7EF39DBA39BDA2FD2AA0A0AAFDAB67821A286D04F1678C89CFD6036094A3F9C36D2C9E48FFE35B95C8A742F553138A8899E2CE63259F6DDC7A4D59868AF8A3F50EC037F1DAB73827B5D906A115C28FC8E4B744D661AF77592955F525E236D;域= 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?我错过了什么?

谢谢。

回答

1

我想我发现了这个问题:验证用户(并生成cookie)的$ .ajax方法调用没有withCredentials字段,所以从服务器返回的cookie最终被丢弃。

+0

谢谢。我有类似的问题。你能多解释一下吗?什么方法调用没有通过withCredentials字段>? –

+0

当然。如果我没有弄错,你需要将xhrFields对象添加到执行用户验证和认证的$ ajax调用中。仅在后续请求中使用它(即验证后执行的请求)将不起作用。 –

+0

好的,谢谢你。我认为这就是你的意思。 –