C# 如何基于索赔原则创建身份用户

C# 如何基于索赔原则创建身份用户,c#,asp.net,entity-framework,C#,Asp.net,Entity Framework,我正在使用asp.net mvc进行工作/学校帐户身份验证。目前,我正在尝试将标识实现到用户进程中 这是我的ApplicationUser课程: 公共类应用程序用户:IdentityUser { 公共ICollection学期{get;set;} } 到目前为止,身份识别工作正常,只有一个问题。当我使用我的学校帐户登录应用程序时,我可以在控制器中以User的身份调用ClaimsPrincipals。要获取当前的应用程序用户,您可以使用用户管理器(await\u UserManager.GetU

我正在使用asp.net mvc进行工作/学校帐户身份验证。目前,我正在尝试将标识实现到用户进程中

这是我的
ApplicationUser
课程:

公共类应用程序用户:IdentityUser
{
公共ICollection学期{get;set;}
}
到目前为止,身份识别工作正常,只有一个问题。当我使用我的学校帐户登录应用程序时,我可以在控制器中以
User
的身份调用
ClaimsPrincipals
。要获取当前的
应用程序用户
,您可以使用
用户管理器
await\u UserManager.GetUserAsync(User)
,其中
User
ClaimsPrincipals
),但由于我没有在数据库中存储我的学校帐户,因此结果将为空。如果我创建一个新的
应用程序用户
,如下所示

var newUser=newapplicationuser()
{
用户名=User.Identity.Name,
电子邮件=User.Identity.Name
};
wait\u userManager.CreateAsync(newUser);
wait_userManager.AddClaimsAsync(newUser,User.Claims);

这将成功地创建新用户并将其保存到包含声明的数据库中。但是,当我尝试使用
await\u userManager.GetUserAsync(User)
获取新创建的
ApplicationUser
时,结果仍然为空。如果访问我的
DbContext
并获取所有
ApplicationUser
,则新创建的
ApplicationUser
就在那里。那么,如何根据我从学校帐户登录中获得的
索赔信息创建
应用程序用户

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

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

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

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

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

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

这要归功于@poke

内部用于检索用户的用户id,然后用于从用户存储(即您的数据库)查询对象

GetUserId
基本上如下所示:

public string GetUserId(ClaimsPrincipal principal)
{
    return principal.FindFirstValue(Options.ClaimsIdentity.UserIdClaimType);
}
因此,这将返回
Options.ClaimsIdentity.UserIdClaimType
的索赔值<代码>选项
是您配置标识时使用的选项。默认情况下,
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";
});
资料来源:


这要归功于@poke

内部用于检索用户的用户id,然后用于从用户存储(即您的数据库)查询对象

GetUserId
基本上如下所示:

public string GetUserId(ClaimsPrincipal principal)
{
    return principal.FindFirstValue(Options.ClaimsIdentity.UserIdClaimType);
}
因此,这将返回
Options.ClaimsIdentity.UserIdClaimType
的索赔值<代码>选项是您配置标识时使用的选项。默认情况下,
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";
});
资料来源:


可能您需要刷新声明,因为新创建的用户可能还不存在。如果在数据库中创建的很好,请尝试使用
await\u-signInManager.RefreshSignInAsync(applicationUser)刷新声明await\u userManager.AddClaimsAsync(newUser,User.Claims)后的code>
@Dave这给了我以下错误:
InvalidOperationException:没有为方案“Identity.Application”注册身份验证处理程序。注册计划有:AzureAD、AzureADOpenID、Azureadocookie。您是否忘记调用AddAuthentication()。添加[SomeAuthHandler](“Identity.Application”,…)?
。基于此,我想到了做
wait\u userManager.AddLoginAsync(user,loginInfo)
。但我不知道如何找回日志