CreateUserIdenityAsync返回"未找到UserId"自定义IdentityUser的例外

时间:2016-01-22 12:19:24

标签: c# asp.net-web-api asp.net-identity

我跟随bitoftech tutorial关于使用JWT创建基于身份和角色的声明。我的应用程序用户是一个带有int PK的自定义User表。

目前,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;
}

我的UserManager类定义如下:

public class AppUserManager : UserManager<User, int>

奇怪的是,当我调试时,this中的实例GenerateIdentityAsync确实有UserId属性,但基数只有id,我想知道是不是 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. 它出错的地方? (听起来不对)

我正在查看source code(第80行),但我无法确定抛出异常的位置。

抛出的确切异常是:

GrantResourceOwnerCredentials()

stack trace并非对我有用(

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

模式详情:

我的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; } }

_1

6 个答案:

答案 0 :(得分:5)

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

您需要从UserId课程中删除User,使用Id中的基础IdentityUser并重命名自定义用户表格中的UserId列到Id

User类中的任何属性都需要在数据库的用户表中包含匹配的列。如果没有,那么对于不匹配的属性,您将得到相同的错误。

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

答案 1 :(得分:3)

您的UserId课程中IdUser属性都有Id继承自IdentityUser。问题是您可能已将UserId配置为User的主键。

ClaimsIdentityFactory.CreateAsync UserManager.GetSecurityStampAsync方法在[{3}} 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(继承自// C#, all versions private readonly int _foo; public int Foo { get { return _foo; } } // C#, version 6+ // actually, this is the same as above, but backing field is generated // for you by compiler public int Foo { get; } )。

答案 2 :(得分:2)

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

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context){}

Taiseer对GrantResourceOwnerCredentials的评论是:

  

&#34;我们正在为登录用户构建一个身份,即此身份   将包含经过身份验证的用户的所有角色和声明&#34;

我必须将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()));

答案 3 :(得分:2)

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

但是,如果您将Id属性的数据类型更改为int并且未在构造函数中为该属性提供值,则Identity仍会尝试使用默认的int值(0)来检索用户详细信息抛出消息&#34; System.InvalidOperationException:找不到UserId&#34;。

我通过command.ExecuteScalar()从数据库中检索值来解决这个问题,并将值赋给user.Id. 希望这有助于某些人面临类似的问题。

答案 4 :(得分:0)

在我的情况下,发生此错误是因为我在帐户控制器的Login方法中添加了另一个SignInManager(以下是添加角色的示例)。它在同一方法中执行SignInManager.PasswordSignInAsync和SignInManager.SignInAsync,并两次在ApplicationUser中调用GenerateUserIdentityAsync(...),第一个成功,第二个给了我“ UserId”异常。

答案 5 :(得分:-1)

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