81

我正在開發一個MVC 5 Web應用程序使用實體框架5數據庫優先方法。我正在使用OWIN進行用戶驗證。以下顯示我的帳戶控制器中的我的登錄方法。MVC 5訪問聲明標識用戶數據

public ActionResult Login(LoginViewModel model, string returnUrl) 
{ 
    if (ModelState.IsValid) 
    { 
     var user = _AccountService.VerifyPassword(model.UserName, model.Password, false); 
     if (user != null) 
     { 
      var identity = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, model.UserName), }, DefaultAuthenticationTypes.ApplicationCookie, ClaimTypes.Name, ClaimTypes.Role); 

      identity.AddClaim(new Claim(ClaimTypes.Role, "guest")); 
      identity.AddClaim(new Claim(ClaimTypes.GivenName, "A Person")); 
      identity.AddClaim(new Claim(ClaimTypes.Sid, user.userID)); //OK to store userID here? 

      AuthenticationManager.SignIn(new AuthenticationProperties 
      { 
       IsPersistent = model.RememberMe 
      }, identity); 

      return RedirectToAction("Index", "MyDashboard"); 
     } 
     else 
     { 
      ModelState.AddModelError("", "Invalid username or password."); 
     } 
    } 
    // If we got this far, something failed, redisplay form 
    return View(model); 
} 

正如你可以看到我創建一個ClaimsIdentity和增加幾個聲稱它,然後將它傳遞給OWIN使用的AuthenticationManager執行的標誌。

的我遇到的問題是我不確定如何訪問我的應用程序的其餘部分的聲明,無論是在控制器還是在Razor Views中。

我曾但是試圖在本教程中

http://brockallen.com/2013/10/24/a-primer-on-owin-cookie-authentication-middleware-for-the-asp-net-developer/

例如,我試圖以訪問傳遞到索賠值嘗試這在我的控制器代碼中列出的方法,該user.Claims等於null

var ctx = HttpContext.GetOwinContext(); 
ClaimsPrincipal user = ctx.Authentication.User; 
IEnumerable<Claim> claims = user.Claims; 

也許我在這裏錯過了一些東西。

UPDATE

根據達林的回答,我加了他的代碼,但我仍看不到獲得索賠。請看下面的屏幕截圖,展示我在身份超過時看到的內容.Claims。

enter image description here

+0

你能確認cookie是由瀏覽器發回嗎?也許你的安全設置需要SSL? – leastprivilege

+0

@leastprivilege謝謝,我現在來看看。我發現這個問題在Stackoverflow,http://stackoverflow.com/questions/20319118/i-cant-seem-to-get-a-very-basic-cookie-login-example-to-work-with-mvc5-and -owin?rq = 1這與我所遇到的完全相同,但不幸的是沒有回答:( – tgriffiths

+0

你的OWIN組件是如何初始化的? –

回答

109

試試這個:

[Authorize] 
public ActionResult SomeAction() 
{ 
    var identity = (ClaimsIdentity)User.Identity; 
    IEnumerable<Claim> claims = identity.Claims; 
    ... 
} 
+0

感謝您的幫助。你在控制器中的一個Action中的建議答案,試圖訪問Claim值,但是,我的identity.Claims仍然是NULL(請參閱更新後的問題,帶有截圖)任何其他想法?我感謝你的幫助 – tgriffiths

+0

不,沒有其他想法,這一直對我有用 –

+0

沒有probs,無論如何,謝謝 – tgriffiths

27

你也可以這樣做:

//Get the current claims principal 
var identity = (ClaimsPrincipal)Thread.CurrentPrincipal; 
var claims = identity.Claims; 

更新

提供進一步的解釋爲每個評論。

如果要創建系統內的用戶,如下所示:

UserManager<applicationuser> userManager = new UserManager<applicationuser>(new UserStore<applicationuser>(new SecurityContext())); 
ClaimsIdentity identity = userManager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie); 

您應該自動填充有關於你的身份有些說法。

要添加自定義的權利要求用戶通過驗證,你可以做到這一點,具體如下:

var user = userManager.Find(userName, password); 
identity.AddClaim(new Claim(ClaimTypes.Email, user.Email)); 

的索賠可以退了出去讀作達林已高於或因爲我有回答。當你調用下面路過的身份

權利要求書堅持:

AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = persistCookie }, identity); 

本文介紹得更詳細些,是具體到MVC 5,我所知道的其他文章的目的是MVC 4。

http://kevin-junghans.blogspot.co.uk/2013/12/using-claims-in-aspnet-identity.html

+0

謝謝,但這仍然不適合我。你能看到我更新的問題嗎?另外,還有最後一個問題。我是否需要在Global.asax中創建自己的自定義ClaimsAuthenticationManager類和Application_PostAuthenticateRequest(),如http://dotnetcodr.com/2013/02/25/claims-based-authentication-in-mvc4-with-net4-5-上面的代碼之前的c-part-1-claims-transformation /會起作用嗎?再次感謝你的幫助。 – tgriffiths

+0

嗨,我回頭看個人電腦時會看一看。 – hutchonoid

+0

謝謝,真的很感激。在一個階段,這是開始打擊我:) – tgriffiths

10

你也可以做到這一點。

IEnumerable<Claim> claims = ClaimsPrincipal.Current.Claims; 
6

要在Darin的回答進一步的聯繫,您可以通過使用使用FindFirst方法讓您的具體要求:

var identity = (ClaimsIdentity)User.Identity; 
var role = identity.FindFirst(ClaimTypes.Role).Value; 
+0

或者這個也是 string myValue = identity.FindFirstValue(「MyClaimType」); –

6
Request.GetOwinContext().Authentication.User.Claims 

但是最好是裏面添加了索賠「 GenerateUserIdentityAsync「方法,特別是如果啓動了Startup.Auth.cs中的regenerateIdentity。

+0

'GenerateUserIdentityAsync'是一個很棒的建議,我完全忽略了它。非常感謝羅勒。 – timmi4sa

13

如果您不想一直使用索賠,這是一種選擇。看看Ben Foster的tutorial

public class AppUser : ClaimsPrincipal 
{ 
    public AppUser(ClaimsPrincipal principal) 
     : base(principal) 
    { 
    } 

    public string Name 
    { 
     get 
     { 
      return this.FindFirst(ClaimTypes.Name).Value; 
     } 
    } 

} 

然後你就可以添加一個基本的控制器。

public abstract class AppController : Controller 
{  
    public AppUser CurrentUser 
    { 
     get 
     { 
      return new AppUser(this.User as ClaimsPrincipal); 
     } 
    } 
} 

在你控制,你會怎麼做:

public class HomeController : AppController 
{ 
    public ActionResult Index() 
    { 
     ViewBag.Name = CurrentUser.Name; 
     return View(); 
    } 
} 
5

請記住,爲了查詢你需要引用System.Linq的了IEnumerable。
它會給你做所需要的擴展對象:

CaimsList.FirstOrDefault(x=>x.Type =="variableName").toString(); 
14

我做我自己的擴展類,看看我需要什麼,所以當我需要爲我的控制器或我的看法,我只用添加到我的命名空間是這樣的:

public static class UserExtended 
{ 
    public static string GetFullName(this IPrincipal user) 
    { 
     var claim = ((ClaimsIdentity)user.Identity).FindFirst(ClaimTypes.Name); 
     return claim == null ? null : claim.Value; 
    } 
    public static string GetAddress(this IPrincipal user) 
    { 
     var claim = ((ClaimsIdentity)user.Identity).FindFirst(ClaimTypes.StreetAddress); 
     return claim == null ? null : claim.Value; 
    } 
    public .... 
    { 
     ..... 
    } 
} 

在我的控制器:

using XXX.CodeHelpers.Extended; 

var claimAddress = User.GetAddress(); 

在我的剃鬚刀:

@using DinexWebSeller.CodeHelpers.Extended; 

@User.GetFullName() 
+4

'return claim?.Value;'因爲爲什麼不 – Halter

2

根據ControllerBase類,您可以獲取執行該操作的用戶的聲明。

enter image description here

這裏是你如何能在1行做到這一點。

var claims = User.Claims.ToList(); 
4

最短和簡化@Rosdi Kasim'd回答的版本是

string claimvalue = ((System.Security.Claims.ClaimsIdentity)User.Identity). 
    FindFirst("claimname").Value; 

Claimname是要找回我的要求。如果你正在尋找「StreedAddress」聲明,那麼上述答案將是這樣的

string claimvalue = ((System.Security.Claims.ClaimsIdentity)User.Identity). 
    FindFirst("StreedAddress").Value;