【问题标题】:Weird AJAX redirect 401 issue with IISIIS 出现奇怪的 AJAX 重定向 401 问题
【发布时间】:2015-07-01 10:20:15
【问题描述】:

我应该删除这个问题吗? 我弄清楚问题出在哪里,而不是 IIS...请参阅下面的答案以了解结果。

原始问题 我正在开发一个 ASP.Net MVC 应用程序,但遇到了 URL 重写重定向和 AJAX 请求的奇怪问题。

我在根站点的 Web.config 中添加了以下重写规则。

<rewrite>
    <rules>
        <rule name="Account" stopProcessing="true">
            <match url="^SubApp/Account/(.*)$" />
            <action type="Redirect" url="Account/{R:1}" redirectType="Found" />
        </rule>
    </rules>
</rewrite>

如果我在配置中使用PermanentTemporary redirectType 但失败并出现HTTP Error 401.0 - Unauthorized IIS 错误页面,一切似乎都正常。

当我通过浏览器向会触发此规则的操作发出正常的 GET 请求时,例如https://some-site/SubApp/Account/Settings 然后我得到一个 302 Found 并且位置标头设置为预期的 URL https://some-site/Account/Settings 并呈现相应的页面。

但是,当我通过 JQuery 的 AJAX 即 $.get('https://some-site/SubApp/Account/Settings') 发出 GET 请求时,返回的响应状态代码是 401 Unauthorized 但它仍然具有适当的位置标头。

响应的内容是一个标准的 IIS HTTP Error 401.0 - Unauthorized 错误页面。

奇怪的是,如果我在配置中使用PermanentTemporary 重定向类型,但只有Found 失败,一切似乎都正常。

/SubApp 是一个单独的应用程序,位于 / 的根站点下方。

发生了什么事?

截图

redirectType="Permanent"

redirectType="Found"

redirectType="Temporary"

从屏幕截图中可以看出,唯一的区别是 Web.config 中指定的 redirectType

正如您所见,重定向正在按预期发生,但 Found 重定向类型除外,我希望得到 302 - Found 响应重定向到与其他重定向相同的 URL。

【问题讨论】:

  • 可以添加代码吗?
  • 您能否为两种情况(工作/不工作)添加网络流量的屏幕截图?
  • 我能做到,但这是一个相当大的$.get("/BMS/Account/Settings")。我将用一些屏幕截图更新问题...
  • 我怀疑您遇到了不同来源的问题。对虚拟 url 使用 url 助手和 tilda 斜线被认为是更好的做法,让框架解决问题。这样您就不太可能得到基于 401 的错误来源。
  • @DaveAlperovich - 如果是这种情况,为什么它适用于 PermanentTemporary 重定向?

标签: ajax asp.net-mvc iis


【解决方案1】:

啊,你知道,当你有一段时间不去想某事时,你会突然受到启发……好吧,昨晚发生了,我发现这个小金块可以“修复”MVC 对重定向的坚持身份验证失败时的 AJAX 请求...

protected void Application_EndRequest()
{
    var context = new HttpContextWrapper(Context);
    // MVC retuns a 302 for unauthorized ajax requests so alter to request status to be a 401
    if (context.Response.StatusCode == 302 && context.Request.IsAjaxRequest() && !context.Request.IsAuthenticated)
    {   
        context.Response.Clear();
        context.Response.StatusCode = 401;
    }
}

而且,不出所料,context.Request.IsAuthenticated 总是假的,因为它似乎被重定向重置了。

Branislav Abadjimarinov's blog post 的帮助下对此进行了更新。

protected void Application_EndRequest()
{
    var context = new HttpContextWrapper(Context);
    // MVC returns a 302 for unauthorized ajax requests so alter to request status to be a 401

    if (context.Response.StatusCode == 302 && context.Request.IsAjaxRequest())
    {
        //Unfortunately the redirect also clears the results of any authentication
        //Try to manually authenticate the user...
        var authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
        if (authCookie != null)
        {
            var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
            if (authTicket != null && !authTicket.Expired)
            {
                var roles = authTicket.UserData.Split(',');
                HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(authTicket), roles);
            }
        }

        if (!context.Request.IsAuthenticated)
        {
            context.Response.Clear();
            context.Response.StatusCode = 401;
        }

    }
}

这一切都按预期工作。

唯一的问题是我应该删除这个问题吗?

【讨论】:

  • 请勿删除,可能对以后的访问者有帮助
【解决方案2】:

看看这个Cannot handle 302 redirect in ajax and why? [duplicate],看起来网络浏览器看到了 Found-302 并对其执行了操作。

【讨论】:

  • 明天我会再次检查,但会话已完全通过身份验证,我看到一个带有位置标头的 301,然后是浏览器对新位置的后续请求,当它是 200 状态响应时设置为Permanent 我看到完全一样,除了当redirectType 设置为Temporary 时第一个响应的307 状态代码。当它设置为Found 时,我得到一个 401 但奇怪的是位置标头设置为我期望重定向指向的资源。我没有尝试手动处理重定向,并且位置标头指向正确的资源。
  • Brian,我可能遗漏了一些东西,但您发布的链接似乎是关于不将未经授权的请求重定向到授权页面 bc 页面重定向不能在 ajax 中发生。如果是这样,我对 OP 问题的理解就完全不同了。
猜你喜欢
  • 2011-08-05
  • 2015-12-13
  • 1970-01-01
  • 2013-12-17
  • 2014-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-10
相关资源
最近更新 更多