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

非常感謝,它爲我工作。 –