【发布时间】:2014-03-29 07:57:07
【问题描述】:
我们目前正在开发一个 ASP.NET MVC 5.1 应用程序,用于部署到我们不会控制其 IIS 配置的客户站点。该应用程序使用 ASP.NET Identity 2.0.0 进行身份验证和用户管理。在内部测试期间,我们在运行 Windows Server 2012 R2 和 IIS 8 的测试服务器上的虚拟目录中(作为单独的应用程序和单独的应用程序池下)有不同的实例。
我报告了一个错误,即尝试使用以下 URL 登录 -
https://server.domain.com/VirtualDirectory/Account/Login?ReturnUrl=%2fVirtualDirectory
导致用户 登录但被重定向回登录页面而不是应用程序根/主页的循环。这里明显的突出点是虚拟目录名称中缺少尾部斜杠。如果提供了编码的斜杠,或者 returnUrl 被省略或不是本地 URL,则应用程序正确重定向成功。
这不是我们的登录逻辑的问题,因为用户已经登录并且在应用程序的根目录中,只需删除后面的斜杠即可将其重定向回登录页面要离开的虚拟目录名-
根据IIS generates courtesy redirect when folder without trailing slash is requested-
"当浏览器请求一个 URL 时,例如 http://www.servername.de/SubDir,浏览器被重定向到 http://www.servername.de/SubDir/。尾部斜杠包含在 URL 的结尾... Internet 信息服务器 (IIS) 首先将 SubDir 视为应返回给浏览器的文件。如果找不到此文件,IIS 将检查是否存在具有此名称的目录。 如果存在同名目录,则会向浏览器返回带有 302“对象已移动”响应消息的礼貌重定向。此消息还包含有关带有尾部斜杠的目录的新位置的信息。反过来,浏览器会向带有斜杠的 URL 发起一个新的 GET 请求。”
事实上,虽然我得到了 Fiddler 的以下回复-
获取https://server.domain.com/VirtualDirectory
302 重定向到 /VirtualDirectory/Account/Login?ReturnUrl=%2fVirtualDirectory
默认路由未从 Microsoft 模板修改-
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
家庭控制器装饰有 [Authorize] 属性,这当然需要未经身份验证的用户才能登录。
与身份验证相关的 Web.config 设置是 -
<authentication mode="None">
<forms cookieless="UseCookies" loginUrl="~/Account/Login" name="OurCompanyAuthentication" timeout="120" />
</authentication>
<authorization>
<allow users="?" />
<allow users="*" />
</authorization>
forms 元素已通过实验证明是必要的,以正确映射到登录页面并防止继承配置在应用程序的根目录中查找 login.aspx 页面。该配置与 Startup.Auth.cs 的配置相匹配,即-
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
CookieHttpOnly = true, //In supported browsers prevent JavaScript from accessing the authentication cookie
CookieName = "OurCompanyAuthentication",
CookiePath = VirtualPathUtility.ToAbsolute("~/"),
ExpireTimeSpan = new TimeSpan(hours: 2, minutes: 0, seconds: 0), //Cookie expires two hours after it is issued
LoginPath = new PathString("/Account/Login"),
SlidingExpiration = true //Cookie will be re-issued on requests more than halfway through expiration window
});
问题-
什么是无条件地生成 302 重定向到登录页面,且 returnUrl 未修改/不正确(无论用户是否已经登录,都会发生这种情况),以及如何恢复所描述的行为执行带有斜杠的 302 重定向。
如果我可以有条件地使用正确的返回 URL 定向到登录页面,那就更好了,但主要要求是首先避免错误地重定向到登录页面和后续循环。如果 302 重定向到应用程序根目录,然后进一步重定向到登录页面(用户未通过身份验证或他们的票已过期),那么这是可以接受的。
我研究过 URL 重写,但开发人员事先不知道域和虚拟路径,因为每个客户站点上的这些可能不同 - 主机服务器上虚拟目录的使用或其他方式也是如此。
【问题讨论】:
-
尝试
CookiePath = VirtualPathUtility.ToAbsolute("~")注意斜线不存在
标签: asp.net-mvc iis asp.net-identity virtual-directory asp.net-mvc-5.1