lea*_*... 8 c# asp.net claims-based-identity asp.net-identity
我有一个问题,理解索赔,特别是角色.
以下给我分配给用户的两个角色
var roles = UserManager.GetRolesAsync(user.Id).Result;
Run Code Online (Sandbox Code Playgroud)
但是,当我得到索赔并迭代它时,我只获得第一个角色.我没有得到这两个角色.请注意,我在登录时没有在索赔中设置任何角色.
行动守则
IEnumerable<Claim> claims = null;
var identity = HttpContext.User.Identity as ClaimsIdentity;
if (identity != null && identity.Claims != null && identity.Claims.Any())
{
claims = identity.Claims;
}
return View(claims);
Run Code Online (Sandbox Code Playgroud)
和相应的视图代码
@model IEnumerable<System.Security.Claims.Claim>
@{
ViewBag.Title = "Display Claims";
}
<h2>Display Claims</h2>
@if (Model == null)
{
<p class="alert-danger">No claims found</p>
}
else
{
<table class="table table-bordered">
<tr>
<th>Subject</th>
<th>Issuer</th>
<th>Type</th>
<th>Value</th>
</tr>
@foreach (var claim in Model.OrderBy(x => x.Type))
{
<tr>
<td>@claim.Subject.Name</td>
<td>@claim.Issuer</td>
<td>@Html.ClaimType(claim.Type)</td>
<td>@claim.Value</td>
</tr>
}
</table>
}
Run Code Online (Sandbox Code Playgroud)
这是输出.我在这里错过了什么?
表格有两个角色
更新#1
我添加了名字和姓氏作为远程声明,登录并且两个角色现在都在显示.我没有改变任何事情.所以现在我更困惑了......
以下是添加远程声明的提供程序
public static class ClaimsUserInfoProvider
{
public static IEnumerable<Claim> GetClaims(ClaimsIdentity user, ApplicationUser applicationUser)
{
var claims = new List<Claim>();
claims.Add(CreateClaim(ClaimTypes.GivenName, applicationUser.FirstName + " " + applicationUser.LastName));
return claims;
}
private static Claim CreateClaim(string type, string value)
{
return new Claim(type, value, ClaimValueTypes.String, "RemoteClaims");
}
}
Run Code Online (Sandbox Code Playgroud)
以及使用声明提供程序的登录操作
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model)
{
if (ModelState.IsValid)
{
var user = await UserManager.FindAsync(model.UserName, model.Password);
if (user == null)
{
ModelState.AddModelError("", "Invalid user name or password.");
}
else
{
var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
//add claims
identity.AddClaims(ClaimsUserInfoProvider.GetClaims(identity, user));
AuthenticationManager.SignOut();
AuthenticationManager.SignIn(new AuthenticationProperties
{
IsPersistent = model.RememberMe
}, identity);
if (!String.IsNullOrEmpty(model.ReturnUrl))
{
return Redirect(model.ReturnUrl);
}
return RedirectToAction("Index", "Home");
}
}
return View(model);
}
Run Code Online (Sandbox Code Playgroud)
很难确定,但我认为这里发生的情况是声明被缓存在用于验证用户身份的 cookie 中。当用户首次登录时,将从数据库中读取声明,并使用声明创建一个 cookie 并将其存储在用户浏览器上。所有进一步的请求都会从 cookie 中读取用户声明信息,直到 cookie 过期。我之前写过一篇关于ASP.NET Identity Cookie Expiration 的详细博客文章,以获取有关如何管理过期的更多信息。
您的一些措辞表明(仅是我的猜测)角色是在用户登录后添加的,因此角色未添加到 cookie 中并且不会打印出来。当您添加代码来添加名称时,声明会刷新,原因如下:
您保持登录状态,但当您重新发布到login您调用的操作signout时,signin该操作刷新了 cookie:
AuthenticationManager.SignOut();
AuthenticationManager.SignIn(new AuthenticationProperties
您可以复制您所经历的行为:
AspNetUserRoles从表中删除用户的角色AspNetUserRoles(手动或通过您管理用户角色的应用程序通过某些操作)每次添加角色或声明时,您都需要让用户手动注销,或者您可以进行调用来刷新 cookie,如我之前提到的。这里的答案提供了一些有关如何有效刷新 cookie 的背景信息。