【问题标题】:CORS: accessing web services which require authentication (ASP.NET forms)CORS:访问需要身份验证的 Web 服务(ASP.NET 表单)
【发布时间】:2013-09-02 10:50:14
【问题描述】:

我正在尝试在托管多个 WCF 服务的现有 asp.net 网站上启用 CORS。不幸的是,我很难让它发挥作用。乍一看,我被重定向到登录页面(不存在),因此自定义身份验证服务生成的身份验证 cookie 可能有问题。

在继续之前,先简单描述一下我目前的情况:

  • 我有站点 A,它公开了几个 Web 服务(除了 身份验证服务只能由经过身份验证的用户访问), 和站点 B,它有一个尝试与网络交互的页面 服务
  • 为了复制这个场景,我把 services+html 页面在同一个地方,我创建了一个别名 (主机文件)以模拟 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 的示例:

的Set-Cookie:.ASPXAUTH = 1CB7EF39DBA39BDA2FD2AA0A0AAFDAB67821A286D04F1678C89CFD6036094A3F9C36D2C9E48FFE35B95C8A742F553138A8899E2CE63259F6DDC7A4D59868AF8A3F50EC037F1DAB73827B5D906A115C28FC8E4B744D661AF77592955F525E236D;域=outro.pt;路径=/; HttpOnly

乍一看,我看不出这个身份验证 cookie 没有任何问题(我认为它与正确的域相关联,每当我点击 outro.pt 中维护的任何页面时都应该发送它,对吧? - 即使它是放在另一个 asp.net 应用程序中,比如 outro.pt/demo/webservice.ashx?)

由于当我尝试访问第二个 Web 服务时被重定向到登录页面,我认为问题在于没有发送身份验证 cookie。这是正确的:根据提琴手的说法,第二次调用的请求标头中没有发送任何 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?我错过了什么?

谢谢。

【问题讨论】:

    标签: jquery asp.net authentication cookies cross-domain


    【解决方案1】:

    我想我找到了问题所在:用于验证用户(并生成 cookie)的 $.ajax 方法调用没有 withCredentials 字段,因此从服务器返回的 cookie 最终被丢弃了。

    【讨论】:

    • 谢谢。我有类似的问题。你能再解释一下吗?什么方法调用没有传递 withCredentials 字段>?
    • 当然。如果我没记错的话,您需要将 xhrFields 对象添加到执行用户验证和身份验证的 $ajax 调用中。仅在后续请求(即验证后执行的请求)上使用它是行不通的。
    • 好的,谢谢。我以为这就是你的意思。
    猜你喜欢
    • 1970-01-01
    • 2012-02-19
    • 2010-10-04
    • 2020-05-06
    • 2016-06-10
    • 2012-12-10
    • 1970-01-01
    • 2017-02-09
    • 2011-08-03
    相关资源
    最近更新 更多