2016-01-22 3 views
6

Я следую по адресу bitoftech tutorial о создании утверждений с идентификатором и ролью с JWT. Пользователь моего приложения является пользовательской таблицей пользователя с int PK.CreateUserIdenityAsync возвращает исключение «UserId not found» для пользовательского IdentityUser

В настоящее время метод 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, и мне интересно, если это так e это ошибка? (это звучит не так)

Я смотрел на source code (строка 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. 

И stack trace не все, что полезно (для меня)

Как узнать, почему/где UserId не доступен?


детали Режим:

Мои 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; } 
} 
+0

Проверьте в своем aspnet db, если у вас есть правильные имена столбцов (UserId вместо Id или наоборот). Также одна из возможностей - несоответствие типа столбца (uniqueidentifiers по сравнению с nvarchar (256)). – Batuta

ответ

3

Как вы узнали при отладке IdentityUser имеет Id, который в вашем случае будет представлять собой идентификатор пользователя.

Вы должны удалить UserId из вашего User класса, использовать базу Id из IdentityUser и переименовать UserId столбец в пользовательской таблице User в Id.

Любые свойства, которые у вас есть в вашем классе User, также должны иметь соответствующий столбец в вашей пользовательской таблице в базе данных. Если нет, вы получите ту же ошибку для свойств, которые не совпадают.

Это означало бы Fullname, Address и ContactNumber должны иметь соответствующие имена столбцов в таблице AspNetUsers или иначе вы получите ту же ошибку для этих свойств, а также.

+0

привет, сделал эти изменения в шахте, но все же ударил ту же ошибку; Теперь я сомневаюсь, что 'UserId' - это то, что я думаю, что нет внутреннего исключения, только трассировка стека, но к сожалению это не очень помогает. Ваш код выше тянет пользователя дважды, что не является проблемой, если он сработает, я мог бы реорганизовать позже, но он все равно бросает то же самое исключение – LocustHorde

+0

@LocustHorde, я вернулся к чертежной доске и перепроверял вашу проблему. Используя предоставленную вами дополнительную информацию, я смог воссоздать одно и то же исключение, включая внутреннее исключение. 'UserId' должен быть допустимым столбцом в таблице« AspNetUsers ». Я думаю, что предыдущий комментатор также указал на это. – Nkosi

+0

Отлично! После вашего комментария я заметил, что в таблице были два столбца «UserId», а также «Id», а в моем методе семени я просто заполнял «UserId», а «Id» был равен нулю.Когда я попытался войти в систему, по какой-либо причине метод, продолжающий бросать 'UserId', не найден. Как только я вручную изменил нуль на целое число, он начал работать нормально! Поэтому я предполагаю, что мне нужно удалить «Id» и как-то сказать Identity, чтобы использовать «UserId» вместо этого ... – LocustHorde

2

Как выглядит ваш класс 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())); 
+0

Привет, добавлены оба блока кода выше; вы не используете JWT? – LocustHorde

+0

Я попробовал его с 'DefaultAuthenticationTypes.ApplicationCookie' и по-прежнему ту же ошибку, я думаю, я могу исключить, что JWT мешает ему хотя бы на данный момент – LocustHorde

+0

Правильно, я не использовал JWT. – BBauer42

2

Вы оба UserId и Id свойства в вашем User классе - Id наследуется от IdentityUser. Проблема в том, что вы, вероятно, сконфигурировали UserId как первичный ключ для User.

Исключением, которое вы получаете, выбрасывается в метод ClaimsIdentityFactory.CreateAsync, на line 97UserManager.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) вместо.

2

Я столкнулся с такой же проблемой. После большой боли в голове я мог разобраться в реальной проблеме. При изменении типа данных свойства Id класса User на строку, Guid(). ToString() присваивается свойству Id в конструкторе, и одно и то же значение сохраняется в базе данных, а Identity извлекает данные пользователя, используя стоимость.

Однако, если вы изменили тип данных свойства Id на int и не предоставили значение для этого свойства в конструкторе, Identity по-прежнему пытается получить данные пользователя, используя значение по умолчанию int (0) this вызывает сообщение «System.InvalidOperationException: UserId not found».

Я решил это, извлекая значение из базы данных командой.ExecuteScalar() и присваивая значение user.Id. Надеюсь, это поможет кому-то столкнуться с подобной проблемой.

+0

Привет @vkuttyp, о каком конструкторе вы говорите? Благодарю. – chemitaxis

+0

Вы можете поделиться немного более подробной информацией? где вы точно установили этот user.Id? спасибо –

+0

Привет @chemitaxis, конструктор, о котором я упоминал, является конструктором класса IdentityUser. – vkuttyp

Смежные вопросы