3

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

我有一个错误报告,尝试使用URL登录像 -

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

结果在一个循环中,由此用户登录但被重定向回登录页面,而不是应用程序根/主页。这里最明显的突出之处就是缺少来自虚拟目录名称的尾部斜线。如果提供了编码的尾部斜线,或者returnUrl被省略或者不是本地URL,那么应用程序会正确重定向。

这不符合我们的登录逻辑是谁已经登录,并在应用程序的根将被重定向到登录页面的用户的问题简单地由虚拟目录名后除去尾部斜杠免洗

https://server.domain.com/VirtualDirectory

根据IIS generates courtesy redirect when folder without trailing slash is requested -

“当浏览器请求诸如 http://www.servername.de/SubDir的URL时,浏览器被重定向到 http://www.servername.de/SubDir/。在URL的 末尾包含尾部斜杠... Internet信息服务器(IIS)首先将SubDir作为文件回送给浏览器。如果找不到这个文件,IIS会检查是否有这个名字的目录。 如果存在具有此名称的目录,则会向浏览器返回带有302“Object move”响应消息的礼节性重定向。此消息还包含有关以斜线结尾的目录的新位置的信息。反过来,浏览器启动一个新的GET请求与结尾的斜线的网址。”

我其实虽然正从Fiddler-

以下响应GET https://server.domain.com/VirtualDirectory

302重定向到/ VirtualDirectory /帐户/登录?ReturnUrl =%2fVirtualDirectory

默认路由未修改从Microsoft模板-

routes.MapRoute(
       name: "Default", 
       url: "{controller}/{action}/{id}", 
       defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
      ); 

家庭控制器装饰有一个[授权]属性,当然需要一个未经身份验证的用户登录。

Web。有关身份验证的配置设置为─

<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的未改性/ uncorrect(此无论用户是否已经登录,都会发生),以及如何恢复所描述的使用附加斜线执行302重定向的行为。

如果我可以有条件地引导到登录页面与一个正确的返回地址,然后那就更好了,但基本要求是避免在首位的不正确重定向到登录页面和随后的循环。如果302重定向到应用程序根目录,然后又进一步重定向到登录页面(用户没有通过身份验证或他们的票证已过期),那么这是可以接受的。

我看着URL重写,但域和虚拟路径不知道开发商提前,因为这些可能是每个客户的网站不同 - 同样是使用或以其他方式在主机服务器上的虚拟目录。

+0

尝试'CookiePath = VirtualPathUtility.ToAbsolute(“〜”)'注意斜线不存在 – user960567

回答

2

我觉得这个代码应该达到什么样的我在固定失踪斜线和重定向到登录页面方面希望双方如果用户尚未验证保存浪费redirect-

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不会被发送,因此用户永远不会被验证。因此,我已经搬到先前在请求生命周期的事件和简化TO-

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

顺便说一句,该事件确实有与应用程序头相关的应用程序中的更多代码 - 以防表面上多余的返回语句引起任何问题。它在应用程序的上下文中不是多余的。 – pwdst

+0

非常感谢,它为我工作。 –