【问题标题】:How to create identity user based on claims prinicpals [duplicate]如何根据声明主体创建身份用户[重复]
【发布时间】:2020-11-24 07:47:47
【问题描述】:

我正在使用带有工作/学校帐户身份验证的 asp.net mvc。目前我正在尝试在用户进程中实现身份。

这是我的ApplicationUser 课程:

public class ApplicationUser: IdentityUser
{
    public ICollection<Semester> Semesters { get; set; }
}

到目前为止,身份验证工作正常,只有一个问题。当我使用我的学校帐户登录应用程序时,我可以在控制器中将ClaimsPrincipals 称为User。要获取当前的ApplicationUser,您可以使用UserManagerawait _userManager.GetUserAsync(User)UserClaimsPrincipals)但是由于我没有将我的学校帐户存储在数据库中,因此结果将为空。如果我创建一个新的ApplicationUser,如下所示

var newUser = new ApplicationUser()
{
    UserName = User.Identity.Name,
    Email = User.Identity.Name
};
await _userManager.CreateAsync(newUser);
await _userManager.AddClaimsAsync(newUser, User.Claims);

这将成功创建新用户并将其保存到带有声明的数据库中。但是当我尝试使用await _userManager.GetUserAsync(User) 获取新创建的ApplicationUser 时,结果仍然为空。如果我访问我的DbContext 并获得所有ApplicationUsers,则新创建的ApplicationUser 就在那里。那么,如何根据我从学校帐户登录获得的ClaimsPrincipals 创建ApplicationUser

【问题讨论】:

  • 您可能需要刷新声明,因为新创建的用户可能还不存在。如果在数据库中创建良好,请尝试在调用 await _userManager.AddClaimsAsync(newUser, User.Claims); 后使用 await _signInManager.RefreshSignInAsync(applicationUser); 刷新声明
  • @Dave 这给了我以下错误:InvalidOperationException: No authentication handler is registered for the scheme 'Identity.Application'. The registered schemes are: AzureAD, AzureADOpenID, AzureADCookie. Did you forget to call AddAuthentication().Add[SomeAuthHandler]("Identity.Application",...)?。基于此,我有了做await _userManager.AddLoginAsync(user, loginInfo) 的想法。但我不知道如何检索登录信息。 loginInfo 必须是 UserLoginInfo
  • 不幸的是,我不能说可能出了什么问题。可以试试this

标签: c# asp.net entity-framework


【解决方案1】:

感谢@poke。

UserManager.GetUserAsync 内部使用UserManager.GetUserId 检索用户的用户 ID,然后用于从用户存储(即您的数据库)中查询对象。

GetUserId 基本上是这样的:

public string GetUserId(ClaimsPrincipal principal)
{
    return principal.FindFirstValue(Options.ClaimsIdentity.UserIdClaimType);
}

所以这会返回Options.ClaimsIdentity.UserIdClaimType 的声明值。 Options 是您配置身份的IdentityOptions object。默认UserIdClaimType的值为ClaimTypes.NameIdentifier,即"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"

因此,当您尝试使用 UserManager.GetUserAsync(HttpContext.User)(该用户主体拥有 UserID 声明)时,用户管理器只是在寻找不同的声明。

您可以通过切换到ClaimTypes.NameIdentifier 来解决此问题:

new ClaimsIdentity(new[]
{
    new Claim(ClaimTypes.Name, user.UserName),
    new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
})

或者您正确配置身份,以便它使用您的 UserID 声明类型:

// in Startup.ConfigureServices
services.AddIdentity(options => {
    options.ClaimIdentity.UserIdClaimType = "UserID";
});

来源:

https://stackoverflow.com/a/51122850/3850405

【讨论】:

    【解决方案2】:

    来自外部提供商的声明将特定于该提供商。它没有登录到您应用程序中的本地身份存储,它只是声称知道用户是谁。因此,您需要先将用户登录到您的商店(SignInManager),然后才能使用它进行授权。如果您不关心保护资源,只想了解用户,您可以直接映射到您的内部商店

    ASPNET“中间件”需要使用身份验证提供程序拦截标头中的声明,然后在 HttpContext 中设置用户对象。拥有用户后,您需要将本地用户存储映射到学校帐户中的用户存储,然后将声明作为单独的调用从结果中获取。通常电子邮件是主题声明,可用于映射:

        var userName = User.Identity.Name;
        var user = _userManager.FindByNameAsync(userName);
        var claims = _userManager.GetClaimsAsync(user);
    

    【讨论】:

      猜你喜欢
      • 2016-07-31
      • 2018-05-09
      • 2016-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-19
      相关资源
      最近更新 更多