2014-02-10 28 views
0

我已經搜索了很多SO和其他頁面,但仍找不到類似的案例。ASP.NET MVC4身份驗證成功,但在項目構建後缺少角色

我的應用程序使用SimpleMembership。它具有基於角色的用戶菜單,並且大多數操作都與[Authorize(Roles =「aaa,bbb」)]]屬性一致。

在應用程序構建或瀏覽器空閒一段時間後,用戶將被重定向到任何鏈接點擊的登錄頁面。奇怪的是,登錄名仍然有效顯示,但沒有它附加的角色名稱。

用戶可以在上述情況下使用[授權]屬性訪問操作。我想知道是否有我缺少的任何東西,或者只要身份驗證有效,我就可以保持角色信息的活躍?

這裏是從控制器動作代碼來渲染菜單:

public ActionResult Menu() 
    { 
     if (Roles.IsUserInRole("Admin")) 
     { 
      return View("MenuAdmin"); 
     } 
     if (Roles.IsUserInRole("Advising")) 
     { 
      return View("MenuAdvising"); 
     } 
     if (Roles.IsUserInRole("StudentDevelopment")) 
     { 
      return View("MenuStudentDevelopment"); 
     }... 

定製_logonPartial顯示登錄名和角色

> @if (Request.IsAuthenticated) { 
    <text> 
     Logged in: @Html.ActionLink(User.Identity.Name, "Manage", "Account", routeValues: null, htmlAttributes: new { @class = "username", title = "Manage" }) as 
     @String.Join(",", Roles.GetRolesForUser(User.Identity.Name)) 
     @using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm" })) { 
      @Html.AntiForgeryToken() 
      <a href="javascript:document.getElementById('logoutForm').submit()">Log off</a> 
     } 
    </text> 

回答

1

角色信息可作爲長作爲用戶登錄。在您的情況下,您正在呼叫:

Roles.GetRolesForUser(User.Identity.Name) 

獲取角色列表。這實際上會觸發數據庫以獲取角色,因此只要用戶名稱在Identity中可用,它就會返回角色,假定用戶具有分配給他們的角色。如果用戶身份驗證,用戶名應該可用。您正在檢查Request.IsAuthenticated。最好檢查User.Identity.IsAuthenticated。

有一種方法可以在不使用索賠查詢數據庫的情況下獲取角色。一般來說,我不會把這樣的邏輯和訪問系統變量的視圖。我會在我的控制器操作中使用這種方法來獲取角色。

 var prinicpal = (ClaimsPrincipal)Thread.CurrentPrincipal; 
     var roles = prinicpal.Claims.Where(c => c.Type == ClaimTypes.Role).Select(c => c.Value); 
     ViewBag.Roles = roles; 

將您需要的信息放入視圖中的ViewBag或創建一個傳遞給視圖的模型。這種獲取角色的方法不需要往返數據庫。

更新以彌補評論

爲MVC 4標準AuthorizeAttribute使用配置的成員資格和角色提供者(在你的情況SimpleMembership)來獲得角色。它不會假定索賠在哪裏使用,因此它每次都進入數據庫。實際上,它必須兩次訪問數據庫,一次獲取登錄用戶的用戶標識,然後根據該用戶標識獲取角色。效率不高。令人驚訝的是,即使您沒有將任何角色作爲參數傳遞,也不需要授權用戶對角色進行身份驗證。我用探查器驗證了這一點。

爲了使效率更高並且不需要訪問數據庫,您可以編寫自定義的AuthorizeAttribute來使用聲明。 Here is an article that describes how to do this,鏈接到示例源代碼。

我無法解釋你描述的情況,這種情況發生在構建之後。但是,如果您創建自定義屬性並使用它,您將能夠調試並查看究竟發生了什麼。另外我不會擔心太多,因爲它不應該是你在生產中看到的典型場景。

+0

感謝您的回答。情況是:在每次構建之後,當訪問'[Authorize(Roles =「XXX,BBB」)]'actions時,用戶將被重定向到登錄頁面。它不會在'[Authorize]'操作中發生(用戶可以在構建之後訪問)。從我的觀察來看,用戶在構建後仍然登錄,但角色不見了。它是一個數據庫連接超時問題?我想知道在執行action屬性時是否有任何可能的方式來保持角色。謝謝 – horizon1711

+0

請看我更新的答案。 –

+0

我試圖構建旨在模擬失去角色的閒置情況的應用程序。現在解決了「失去角色但經過身份驗證」是IIS應用程序池的空閒超時。延長超時時間,它工作正常。謝謝你的幫助。 – horizon1711