Missing Slash Virtual Directory

We are currently developing an ASP.NET MVC 5.1 application for deployment to client sites where we will not control our IIS configuration. The application uses ASP.NET Identity 2.0.0 for authentication and user management. During internal testing, we have different instances in virtual directories (as separate applications and in separate application pools) on our test server running Windows Server 2012 R2 with IIS 8.

I had an error reporting that trying to login with a url like

https://server.domain.com/VirtualDirectory/Account/Login?ReturnUrl=%2fVirtualDirectory

Results in a loop in which the user is logged in but redirected back to the login page instead of the root / home page of the application. The obvious advantage here is the missing trailing slash from the virtual directory name. If a coded trailing slash is provided, or returnUrl is omitted or not a local URL, the application correctly redirects successful execution.

This is not a problem with our login logic, because a user who is already logged in and at the root of the application will be redirected back to the login page by simply deleting the trailing slash after the virtual directory name leaves

https://server.domain.com/VirtualDirectory

IIS , -

" URL-, http://www.servername.de/SubDir, http://www.servername.de/SubDir/. URL-... Internet Information Server (IIS) SubDir , . , IIS , . , " "302" ". . , GET URL .

Fiddler -

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

[], , , .

Web.config, , -

<authentication mode="None">
   <forms cookieless="UseCookies" loginUrl="~/Account/Login" name="OurCompanyAuthentication" timeout="120" />
</authentication>
<authorization>
   <allow users="?" />
   <allow users="*" />
</authorization>

, , 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 unUmodified/unsorrect ( , ) 302 .

URL- , , . 302 ( ), .

URL-, , - - .

+3
1

, , , , , , -

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

All Articles