ASP.NET身份声明

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)

jst*_*ant 1

很难确定,但我认为这里发生的情况是声明被缓存在用于验证用户身份的 cookie 中。当用户首次登录时,将从数据库中读取声明,并使用声明创建一个 cookie 并将其存储在用户浏览器上。所有进一步的请求都会从 cookie 中读取用户声明信息,直到 cookie 过期。我之前写过一篇关于ASP.NET Identity Cookie Expiration 的详细博客文章,以获取有关如何管理过期的更多信息。

您的一些措辞表明(仅是我的猜测)角色是在用户登录后添加的,因此角色未添加到 cookie 中并且不会打印出来。当您添加代码来添加名称时,声明会刷新,原因如下:

  1. cookie 已过期,您必须重新登录。
  2. 您注销(删除了 cookie),然后重新登录。
  3. 您保持登录状态,但当您重新发布到login您调用的操作signout时,signin该操作刷新了 cookie:

    AuthenticationManager.SignOut(); AuthenticationManager.SignIn(new AuthenticationProperties

您可以复制您所经历的行为:

  1. 确保用户已退出
  2. AspNetUserRoles从表中删除用户的角色
  3. 让用户登录
  4. 将角色添加回表中的用户AspNetUserRoles(手动或通过您管理用户角色的应用程序通过某些操作)
  5. 打印出角色
  6. 您将不会在打印输出中看到角色。
  7. 接下来,注销用户并重新登录,然后您将看到预期的角色。

每次添加角色或声明时,您都需要让用户手动注销,或者您可以进行调用来刷新 cookie,如我之前提到的。这里的答案提供了一些有关如何有效刷新 cookie 的背景信息。