Asp.net mvc 缺少尾部斜杠的虚拟目录

Asp.net mvc 缺少尾部斜杠的虚拟目录,asp.net-mvc,iis,asp.net-identity,virtual-directory,asp.net-mvc-5.1,Asp.net Mvc,Iis,Asp.net Identity,Virtual Directory,Asp.net Mvc 5.1,我们目前正在开发一个ASP.NET MVC 5.1应用程序,用于部署到我们无法控制其IIS配置的客户站点。该应用程序使用ASP.NET Identity 2.0.0进行身份验证和用户管理。在内部测试期间,我们在运行带IIS 8的Windows server 2012 R2的测试服务器上的虚拟目录中有不同的实例(作为单独的应用程序和在单独的应用程序池下) 我有一个错误报告说,试图登录的URL如下- 导致用户登录但重定向回登录页面而不是应用程序根/主页的循环。这里最突出的一点是虚拟目录名缺少尾部斜

我们目前正在开发一个ASP.NET MVC 5.1应用程序,用于部署到我们无法控制其IIS配置的客户站点。该应用程序使用ASP.NET Identity 2.0.0进行身份验证和用户管理。在内部测试期间,我们在运行带IIS 8的Windows server 2012 R2的测试服务器上的虚拟目录中有不同的实例(作为单独的应用程序和在单独的应用程序池下)

我有一个错误报告说,试图登录的URL如下-

导致用户登录但重定向回登录页面而不是应用程序根/主页的循环。这里最突出的一点是虚拟目录名缺少尾部斜杠。如果提供了编码的尾随斜杠,或者省略了returnUrl或不是本地URL,则应用程序将正确地成功重定向

这与我们的登录逻辑无关,因为用户已经登录,并且在应用程序的根目录下,只要删除要离开的虚拟目录名称后的尾随斜杠,就可以重定向回登录页面-

据-

“当浏览器请求URL时,例如 ,浏览器将重定向到 。后面的斜杠包含在 URL结尾…Internet Information Server(IIS)首先将SubDir视为应返回给浏览器的文件。如果找不到此文件,IIS将检查是否存在同名目录。如果存在同名目录,则会移动带有302“对象的礼貌重定向“响应消息将返回到浏览器。此消息还包含有关带有尾随斜杠的目录的新位置的信息。反过来,浏览器会启动一个新的GET请求,该请求指向带有尾随斜杠的URL。“

事实上,我从Fiddler那里得到了以下回应-

得到

302重定向到/VirtualDirectory/Account/Login?返回URL=%2VirtualDirectory

默认路由未从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>
问题-

什么是无条件生成302重定向到登录页面,且返回URL未修改/未更正(无论用户是否已登录,都会发生这种情况),以及如何恢复所描述的执行302重定向并附加斜杠的行为

如果我可以使用正确的返回URL有条件地指向登录页面,那就更好了,但首要要求是首先避免错误地重定向到登录页面和后续循环。如果302重定向到应用程序根,然后再重定向到登录页面(如果用户未经认证或其票证已过期),则这是可以接受的


我已经研究过URL重写,但开发人员事先不知道域和虚拟路径,因为每个客户站点上的域和虚拟路径可能不同,主机服务器上虚拟目录的使用与否也是如此。

我认为这段代码应该达到我想要的效果,即修复丢失的斜杠和重定向到登录页面,如果用户尚未通过身份验证以保存浪费的重定向-

protected void Application_ResolveRequestCache(object sender, EventArgs e)
{
    //If the application is installed in a Virtual Directory and the trailing slash is ommitted then permantently redirect to the default action
    //To avoid wasted redirect do this conditional on the authentication status of the user - redirecting to the login page for unauthenticated users
    if ((VirtualPathUtility.ToAbsolute("~/") != Request.ApplicationPath) && (Request.ApplicationPath == Request.Path))
    {
        if (HttpContext.Current.User.Identity.IsAuthenticated)
        {
            var redirectPath = VirtualPathUtility.AppendTrailingSlash(Request.Path);

            Response.RedirectPermanent(redirectPath);
        }

        var loginPagePath = VirtualPathUtility.ToAbsolute("~/Account/Login");

        Response.StatusCode = 401;
        Response.Redirect(loginPagePath);
    }
}
由于我已将cookie路径设置为应用程序目录,当请求缺少尾随斜杠时,不会发送用户cookie,因此无法对用户进行身份验证。因此,我已移动到请求生命周期早期的事件,并简化为-

protected void Application_BeginRequest(object sender, EventArgs e)
{
    //If the application is installed in a Virtual Directory and the trailing slash is ommitted then permantently redirect to the default action
    //To avoid wasted redirect do this conditional on the authentication status of the user - redirecting to the login page for unauthenticated users
    if ((VirtualPathUtility.ToAbsolute("~/") != Request.ApplicationPath) && (Request.ApplicationPath == Request.Path))
    {
        var redirectPath = VirtualPathUtility.AppendTrailingSlash(Request.Path);

        Response.RedirectPermanent(redirectPath);

        return;
    }
}

顺便说一句,该事件在应用程序中确实有更多与应用程序头相关的代码-以防明显冗余的返回语句引起任何人的关注。它在应用程序上下文中不是冗余的。请尝试
CookiePath=VirtualPath实用性。ToAbsolute(“~”)
注意斜杠不在那里
protected void Application_BeginRequest(object sender, EventArgs e)
{
    //If the application is installed in a Virtual Directory and the trailing slash is ommitted then permantently redirect to the default action
    //To avoid wasted redirect do this conditional on the authentication status of the user - redirecting to the login page for unauthenticated users
    if ((VirtualPathUtility.ToAbsolute("~/") != Request.ApplicationPath) && (Request.ApplicationPath == Request.Path))
    {
        var redirectPath = VirtualPathUtility.AppendTrailingSlash(Request.Path);

        Response.RedirectPermanent(redirectPath);

        return;
    }
}