MVC 5访问声明身份用户数据

时间:2014-01-28 11:53:06

标签: asp.net asp.net-mvc authentication asp.net-mvc-5 claims-based-identity

我正在使用 Entity Framework 5数据库优先方法开发 MVC 5 Web应用程序。我使用 OWIN 进行用户身份验证。下面显示了我的帐户控制器中的登录方法。

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 并向其添加多个声明,然后使用 AuthenticationManager 将其传递给 OWIN 执行登录。

我遇到的问题是,我不确定如何在控制器或Razor视图中访问我应用程序的其余部分中的声明。

我尝试过本教程中列出的方法

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

例如,我在我的Controller代码中试图尝试访问传递给Claims的值,但是user.Claims等于null

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

也许我在这里遗漏了一些东西。

更新

根据Darin的回答,我添加了他的代码,但我仍然看不到索赔的访问权限。请看下面的屏幕截图,显示我在身份上悬停时看到的内容。声明。

enter image description here

12 个答案:

答案 0 :(得分:150)

试试这个:

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

答案 1 :(得分:32)

你也可以这样做:

//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));

当Darin已经回答上述或我已经回答时,可以回读这些声明。

如果您在下面致电以下身份,则声明会保留:

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

答案 2 :(得分:25)

我创建自己的扩展类来查看我需要的东西,所以当我需要进入我的控制器或我的视图时,我只将这个使用添加到我的命名空间:

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()

答案 3 :(得分:16)

如果您不想一直使用声明,则可以选择此选项。请看看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();
    }
}

答案 4 :(得分:10)

您也可以这样做。

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

答案 5 :(得分:10)

要进一步了解Darin的答案,您可以使用 FindFirst 方法获取您的具体声明:

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

答案 6 :(得分:6)

Request.GetOwinContext().Authentication.User.Claims

然而,最好在&#34; GenerateUserIdentityAsync&#34;中添加声明。方法,特别是如果启用了Startup.Auth.cs中的regenerateIdentity。

答案 7 :(得分:6)

@Rosdi Kasim的最短和简化版本的答案是

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

Claimname是您要检索的声明,即如果您正在寻找&#34; StreedAddress&#34;声称上面的答案将是这样的

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

答案 8 :(得分:5)

请记住,为了查询IEnumerable,您需要引用system.linq 它将为您提供所需的扩展对象:

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

答案 9 :(得分:2)

根据ControllerBase类,您可以获得执行操作的用户的声明。

enter image description here

这是你如何在一行中完成的。

var claims = User.Claims.ToList();

答案 10 :(得分:1)

var claim = User.Claims.FirstOrDefault(c => c.Type == "claim type here");

答案 11 :(得分:0)

我像在我的基本控制器中那样使用它。只需共享即可使用。

    public string GetCurrentUserEmail() {
        var identity = (ClaimsIdentity)User.Identity;
        IEnumerable<Claim> claims = identity.Claims;
        var email = claims.Where(c => c.Type == ClaimTypes.Email).ToList();
        return email[0].Value.ToString();
    }

    public string GetCurrentUserRole()
    {
        var identity = (ClaimsIdentity)User.Identity;
        IEnumerable<Claim> claims = identity.Claims;
        var role = claims.Where(c => c.Type == ClaimTypes.Role).ToList();
        return role[0].Value.ToString();
    }