IIS 的奇怪 AJAX 重定向 401 问题
Weird AJAX redirect 401 issue with IIS
我应该删除这个问题吗?
我弄清楚问题出在哪里,但不是 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>
如果我在配置中使用 Permanent
或 Temporary
redirectType
似乎一切正常,但失败并出现 HTTP Error 401.0 - Unauthorized
IIS 错误页面。
当我通过浏览器向会触发此规则的操作发出正常的 GET 请求时,例如https://some-site/SubApp/Account/Settings
然后我得到一个 302 Found 并且位置 header 设置为预期的 URL https://some-site/Account/Settings
并呈现适当的页面。
然而,当我通过 JQuery 的 AJAX 发出 GET 请求时,即 $.get('https://some-site/SubApp/Account/Settings')
返回的响应状态代码是 401 Unauthorized
但它仍然有适当的位置 header。
响应的内容是一个标准的 IIS HTTP Error 401.0 - Unauthorized
错误页面。
奇怪的是,如果我在配置中使用 Permanent
或 Temporary
重定向类型,一切似乎都正常,但仅在 Found
.
时失败
/SubApp
是一个单独的应用程序,位于 /
.
的根站点下方
怎么回事?
截图
redirectType="Permanent"
redirectType="Found"
redirectType="Temporary"
正如您从屏幕截图中看到的,唯一的区别是 Web.config
中指定的 redirectType
。
如您所见,重定向按预期发生,但 Found
重定向类型除外,我希望得到 302 - Found
响应重定向到与其他。
看看这个 Cannot handle 302 redirect in ajax and why? [duplicate],网络浏览器似乎看到了 Found-302 并对其执行了操作。
啊啊啊,你知道当你暂时不去想某件事时,你会突然受到灵感的打击......好吧,它发生在昨晚,我发现这个小金块放在 "fix" 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;
}
}
}
一切都按预期进行。
唯一的问题是我应该删除这个问题吗?
我应该删除这个问题吗? 我弄清楚问题出在哪里,但不是 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>
如果我在配置中使用 Permanent
或 Temporary
redirectType
似乎一切正常,但失败并出现 HTTP Error 401.0 - Unauthorized
IIS 错误页面。
当我通过浏览器向会触发此规则的操作发出正常的 GET 请求时,例如https://some-site/SubApp/Account/Settings
然后我得到一个 302 Found 并且位置 header 设置为预期的 URL https://some-site/Account/Settings
并呈现适当的页面。
然而,当我通过 JQuery 的 AJAX 发出 GET 请求时,即 $.get('https://some-site/SubApp/Account/Settings')
返回的响应状态代码是 401 Unauthorized
但它仍然有适当的位置 header。
响应的内容是一个标准的 IIS HTTP Error 401.0 - Unauthorized
错误页面。
奇怪的是,如果我在配置中使用 Permanent
或 Temporary
重定向类型,一切似乎都正常,但仅在 Found
.
/SubApp
是一个单独的应用程序,位于 /
.
怎么回事?
截图
redirectType="Permanent"
redirectType="Found"
redirectType="Temporary"
正如您从屏幕截图中看到的,唯一的区别是 Web.config
中指定的 redirectType
。
如您所见,重定向按预期发生,但 Found
重定向类型除外,我希望得到 302 - Found
响应重定向到与其他。
看看这个 Cannot handle 302 redirect in ajax and why? [duplicate],网络浏览器似乎看到了 Found-302 并对其执行了操作。
啊啊啊,你知道当你暂时不去想某件事时,你会突然受到灵感的打击......好吧,它发生在昨晚,我发现这个小金块放在 "fix" 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;
}
}
}
一切都按预期进行。
唯一的问题是我应该删除这个问题吗?