CreateUserIdenityAsync 返回"UserId not found"自定义 IdentityUser 的异常



我正在按照bitoftech教程进行操作,了解如何使用JWT创建基于身份和角色的声明。我的应用程序用户是具有 int PK 的自定义用户表。

目前,GenerateUserIdentityAsync 方法只返回一个奇怪的UserId not found错误。 这是我的代码:

ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, "JWT");

以及User实体中的实施:

public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<User, int> manager, string authenticationType)
{
    //error on this line: CreateIdentityAsync throws error
    var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
    return userIdentity;
}

我的用户管理器类定义如下:

public class AppUserManager : UserManager<User, int>

奇怪的是,当我调试时,GenerateIdentityAsyncthis的实例确实具有UserId属性,但基只有一个id,我想知道这是否是它出错的地方?(听起来不对)

我正在查看源代码(第 80 行),但我无法弄清楚异常被抛出的位置。

引发的确切异常是:

 UserId not found. 
 Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 
Exception Details: 
    System.InvalidOperationException: 
    UserId not found.

堆栈跟踪并不是那么有用(对我来说)

如何找出用户 ID 不可用的原因/位置?


模式详情:

我的GrantResourceOwnerCredentials()

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
    context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] {"*"});
    var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
    User user = await userManager.FindAsync(context.UserName, context.Password);
    if (user == null) // this is NOT null
    {
        context.SetError("invalid_grant", "The username or password is incorrect");
        return;
    }
    // this line fails
    ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, "JWT"); 
    var ticket = new AuthenticationTicket(oAuthIdentity, null);
    context.Validated(ticket);
}

还有ApplicationUser(就我而言,这只是User

public partial class User : IdentityUser<int, CustomUserLogin, CustomUserRole, CustomUserClaim>
{  
    public int UserId { get; set; }
    public string Fullname { get; set; }
    public string Address { get; set; }
    public string ContactNumber { get; set; }
}

正如您在调试时发现的那样,IdentityUser有一个Id,在您的情况下,它将代表用户的 ID。

您需要从 User 类中删除UserId,使用 IdentityUser 中的基Id,并将自定义 User 表中的UserId列重命名为 Id

User类中的任何属性也需要在数据库的用户表中具有匹配的列。如果不是,则对于不匹配的属性,您将收到相同的错误。

这意味着FullnameAddressContactNumber 必须在AspNetUsers表中具有匹配的列名,否则这些属性也会收到相同的错误。

您的User类中同时具有UserIdId属性 - Id继承自IdentityUser。问题是您可能将UserId配置为User的主键。

您得到的异常在ClaimsIdentityFactory.CreateAsync方法中引发,在第 97 行UserManager.GetSecurityStampAsync .如您所见,user.Id用于检索安全标记。

如果你查看内部UserManager.GetSecurityStampAsync你会看到你得到的异常正好在这里抛出:

public virtual async Task<string> GetSecurityStampAsync(TKey userId)
{
    ThrowIfDisposed();
    var securityStore = GetSecurityStore();
    var user = await FindByIdAsync(userId).WithCurrentCulture();
    if (user == null)
    {
        throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound,
            userId));
    }
    return await securityStore.GetSecurityStampAsync(user).WithCurrentCulture();
}

因此,从类中删除UserId属性User并开始使用Id(继承自IdentityUser)。

我遇到了完全相同的问题。经过长时间的头疼,我可以解决真正的问题。将 User 类的 Id 属性的数据类型更改为字符串时,Guid()。ToString() 被分配给构造函数中的 Id 属性,并将相同的值保存到数据库中,Identity 使用该值检索用户详细信息。

但是,如果将 Id 属性的数据类型更改为 int,并且未在构造函数中为该属性提供值,则标识仍会尝试使用默认的 int 值 (0) 检索用户详细信息,这会导致引发消息"System.InvalidOperationException: 找不到 UserId"。

我通过命令从数据库中检索值来解决此问题。ExecuteScalar() 并将值分配给 user.Id。希望这将帮助一些面临类似问题的人。

你的 ApplicationUser 类是什么样的?此方法在您的应用程序中是什么样的?

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context){}

Taiseer对GrantResourceOwnerCredentials的评论是:

"我们正在为登录用户构建一个身份,这个身份 将包含经过身份验证的用户的所有角色和声明"

我不得不将 ClaimTypes.NameIdentifier 添加到 ClaimsIdentity 中才能解决类似的问题。以下是我的 GrantResourceOwnerCredentials 方法的重要部分:

ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
    context.SetError("invalid_grant", "The user name or password is incorrect.");
    return;
}
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()));

就我而言,发生此错误是因为我在帐户控制器中的登录方法中添加了另一个 SignInManager(按照添加角色的示例)。它以相同的方法执行SignInManager.PasswordSignInAsync和SignInManager.SignInAsync,这在ApplicationUser中调用了GenerateUserIdentityAsync(...)两次,第一个成功了,第二个给了我异常"UserId"未找到。

服务器=xxxx;初始目录=xxxx;;用户 ID = xxxx_user;密码=xxxx; 其中用户 ID 中有一个空格,而不是服务器=xxxx;初始目录=xxxx;;用户 ID = xxxx_user;密码=xxxx; 错!!!!!!!请参阅 https://www.connectionstrings.com/sql-azure/进行确认。

相关内容

  • 没有找到相关文章