简体   繁体   English

IIS产生奇怪的AJAX重定向401问题

[英]Weird AJAX redirect 401 issue with IIS

Should I remove this question? 我应该删除这个问题吗? I figured out what the issue was and it wasn't IIS... See my answer below for the outcome. 我弄清楚了问题所在,而不是IIS ...请参阅下面的答案以获取结果。

Original Question I'm working on an ASP.Net MVC app and run in to a weird issue with URL Rewrite redirects and AJAX requests. 原始问题我正在使用ASP.Net MVC应用程序,并遇到URL重写重定向和AJAX请求的奇怪问题。

I've added the following rewrite rule to my Web.config in the root site. 我在根站点的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>

Everything seems to work ok if I use a Permanent or Temporary redirectType in the config but fails with a HTTP Error 401.0 - Unauthorized IIS error page . 如果我在配置中使用PermanentTemporary redirectType ,一切似乎都可以正常运行,但是失败,并显示HTTP Error 401.0 - Unauthorized IIS错误页面。

When I make an normal GET request via the browser to an action that would trigger this rule eg https://some-site/SubApp/Account/Settings then I get a 302 Found and the location header is set to the expected URL https://some-site/Account/Settings and the appropriate page is rendered. 当我通过浏览器向触发该规则的操作发出常规GET请求时,例如https://some-site/SubApp/Account/Settings那么我会找到302,并且位置标头设置为预期的URL https://some-site/Account/Settings并显示相应的页面。

However when I make a GET request via JQuery's AJAX ie $.get('https://some-site/SubApp/Account/Settings') the returned Response status code is 401 Unauthorized but it still has the appropriate location header. 但是,当我通过JQuery的AJAX发出GET请求时,即$.get('https://some-site/SubApp/Account/Settings') ,返回的响应状态代码为401 Unauthorized但它仍具有适当的位置标头。

The content of the response is a standard IIS HTTP Error 401.0 - Unauthorized error page. 响应的内容是标准的IIS HTTP Error 401.0 - Unauthorized错误页面。

Weirdly everything seems to work ok if I use either the Permanent or Temporary redirect types in the config but fails only with Found . 奇怪的是,如果我在配置中使用PermanentTemporary重定向类型,那么一切似乎都可以正常运行,但只能通过Found失败。

/SubApp is a separate application that sits below the root site at / . /SubApp是一个单独的应用程序,位于/的根站点下方。

What's going on? 这是怎么回事?

Screenshots 屏幕截图

redirectType="Permanent" 永久重定向

redirectType="Found" 找到重定向

redirectType="Temporary" 临时重定向

As you can see from the screenshots the only difference is the redirectType specified in the Web.config . 从屏幕截图中可以看到,唯一的区别是Web.config指定的redirectType

As you can see the redirects are happening as expected with exception to the Found redirect type which I would expect to get a 302 - Found response redirecting to the same URL as the others. 如您所见,重定向是按预期发生的,除了Found重定向类型外,我希望得到302 - Found响应重定向到与其他URL相同的URL。

Ahhhh, you know when you don't think about something for a while and you get hit with sudden inspiration... Well it happened last night and I found this little nugget put in place to "fix" MVC's insistance on redirecting AJAX requests when authentication fails... 嗯,您知道当您暂时不考虑某件事时,会突然受到启发……好吧,昨晚发生了,我发现这个小块可以适当地“修正” 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;
    }
}

And, unsuprisingly, context.Request.IsAuthenticated is always false as it appears to get reset by the redirect . 同样, context.Request.IsAuthenticated始终为false,因为它似乎已被redirect重置。

Updated this, with a little help from Branislav Abadjimarinov's blog post on the subject. Branislav Abadjimarinov的有关该主题的博客文章中提供了一些帮助,对此进行了更新。

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;
        }

    }
}

And it all works as expected. 一切都按预期进行。

Only question is should I remove this question? 唯一的问题是我应该删除这个问题吗?

Take a look at this Cannot handle 302 redirect in ajax and why? 看看这个无法处理Ajax中的302重定向,为什么? [duplicate] , it looks like the web browser sees the Found-302 and performs an action on it. [duplicate] ,似乎网络浏览器看到Found-302并对其执行操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM