MVC 5 访问声明身份用户数据
Posted
技术标签:
【中文标题】MVC 5 访问声明身份用户数据【英文标题】:MVC 5 Access Claims Identity User Data 【发布时间】:2014-02-19 17:06:16 【问题描述】:我正在使用 Entity Framework 5 Database First 方法开发一个 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/
例如,我在我的控制器代码中尝试了此操作,以尝试访问传递给声明的值,但是,user.Claims 等于 null
var ctx = HttpContext.GetOwinContext();
ClaimsPrincipal user = ctx.Authentication.User;
IEnumerable<Claim> claims = user.Claims;
也许我在这里遗漏了一些东西。
更新
根据 Darin 的回答,我添加了他的代码,但我仍然看不到对声明的访问权限。请参阅下面的屏幕截图,显示我将鼠标悬停在身份上时看到的内容。声明。
【问题讨论】:
你能确认cookie是浏览器发回的吗?也许您的安全设置需要 SSL? @leastprivilege 谢谢,我现在就调查一下。我在 *** 上发现了这个问题,***.com/questions/20319118/… 这与我遇到的问题完全相同,但不幸的是没有答案:( 你的 OWIN 组件是如何初始化的? 我最近遇到了这样的问题;我希望这个解决方案有所帮助:***.com/questions/34537475/… 【参考方案1】:试试这个:
[Authorize]
public ActionResult SomeAction()
var identity = (ClaimsIdentity)User.Identity;
IEnumerable<Claim> claims = identity.Claims;
...
【讨论】:
感谢您的帮助。我在控制器中的操作中使用了您建议的答案来尝试访问声明值,但是,我的身份。声明仍然为 NULL(请参阅带有屏幕截图的更新问题)。还有其他想法吗?感谢您的帮助。 不,抱歉,我没有其他想法。这一直对我有用。 对不起,最后一个问题。我是否需要像 dotnetcodr.com/2013/02/25/… 这样在 Global.asax 中创建自己的自定义 ClaimsAuthenticationManager 类和 Application_PostAuthenticateRequest() ,然后上面的代码才能工作?再次感谢。 在您第一次授权之前,您在登录方法之后才能访问它,这就是为什么 OP 当时看不到它的原因。如果你想在 Login 方法中加载,此时你必须手动加载。【参考方案2】:您也可以这样做:
//Get the current claims principal
var identity = (ClaimsPrincipal)Thread.CurrentPrincipal;
var claims = identity.Claims;
更新
根据 cmets 提供进一步的解释。
如果您在系统中按如下方式创建用户:
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);
【讨论】:
谢谢,但这仍然对我不起作用。你能看到我更新的问题吗?另外,最后一个问题。我是否需要像 dotnetcodr.com/2013/02/25/… 这样在 Global.asax 中创建自己的自定义 ClaimsAuthenticationManager 类和 Application_PostAuthenticateRequest() ,然后上面的代码才能工作?再次感谢您的帮助。 @tgriffiths 您好,我为您添加了更新。希望提供更多信息。祝你好运。 :) 不幸的是,我没有使用内置的 Entity Framework Code First,例如 UserManager 等。但感谢您的输入。干杯。 哦,对了。好的,你也许可以像我在 MVC 4 中那样做,但我没有在 mvc5 中尝试过。这是一篇很好的文章,我用过...dotnetcodr.com/2013/02/25/… 知道如何在通过 EF 种子方法创建用户时添加声明吗?【参考方案3】:我创建了自己的扩展类来查看我需要什么,所以当我需要进入我的控制器或我的视图时,我只将 using 添加到我的命名空间中,如下所示:
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()
【讨论】:
return claim?.Value;
因为为什么不【参考方案4】:
如果您不想一直使用声明,这是一种替代方法。看看 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】:要进一步了解 Darin 的答案,您可以使用 FindFirst 方法获取您的具体声明:
var identity = (ClaimsIdentity)User.Identity;
var role = identity.FindFirst(ClaimTypes.Role).Value;
【讨论】:
或者这个也是 string myValue = identity.FindFirstValue("MyClaimType"); 如果 FindFirst 没有找到任何“角色”类型的声明会怎样?空异常? var username = identity.FindFirst(ClaimTypes.NameIdentifier).Value;【参考方案6】:你也可以这样做。
IEnumerable<Claim> claims = ClaimsPrincipal.Current.Claims;
【讨论】:
【参考方案7】:请记住,要查询 IEnumerable,您需要参考 system.linq。 它会给你需要做的扩展对象:
CaimsList.FirstOrDefault(x=>x.Type =="variableName").toString();
【讨论】:
【参考方案8】:@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;
【讨论】:
【参考方案9】:Request.GetOwinContext().Authentication.User.Claims
但是,最好在“GenerateUserIdentityAsync”方法中添加声明,尤其是在 Startup.Auth.cs 中启用 regenerateIdentity 的情况下。
【讨论】:
GenerateUserIdentityAsync
是一个很棒的建议,我完全忽略了它。非常感谢罗勒。【参考方案10】:
根据ControllerBase类,可以得到执行动作的用户的声明。
你可以在 1 行中做到这一点。
var claims = User.Claims.ToList();
【讨论】:
【参考方案11】:var claim = User.Claims.FirstOrDefault(c => c.Type == "claim type here");
【讨论】:
【参考方案12】:我在我的基本控制器中使用它。只是分享准备使用。
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();
【讨论】:
以上是关于MVC 5 访问声明身份用户数据的主要内容,如果未能解决你的问题,请参考以下文章
我应该如何处理 Window Phone / WCF / ASP.NET MVC 应用程序的用户身份?