Есть способ получить UserId
из токена сброса пароля, но, на мой взгляд, это сложно и много работы.
Какие значения по умолчанию
Если у вас есть некоторые коды, такие как следующий,
services.AddIdentity<AppUser, AppRole>(options =>
{
...
}
.AddEntityFrameworkStores<AppIdentityDbContext>()
.AddDefaultTokenProviders();
последняя строка .AddDefaultTokenProviders()
добавляет 4 провайдера токенов по умолчанию , которые используются для генерации токенов для сброса паролей, смены электронной почты и изменения параметров номера телефона и для генерации токенов двухфакторной аутентификации в конвейер:
- DataProtectorTokenProvider
- PhoneNumberTokenProvider
- EmailTokenProvider
- AuthenticatorTokenProvider
Первый, DataProtectorTokenProvider
, это то, что мы ищем. Он использует защиту данных для сериализации / шифрования этих токенов.
А в DataProtectorTokenProvider
его защитник имеет значение по умолчанию для имени «DataProtectorTokenProvider» .
Как токены генерируются
Если вы посмотрите на GenerateAsync()
метод внутри DataProtectorTokenProvider
, вы можете сказать, что токен состоит из:
- Ut c метка времени создания токена (
DateTimeOffset.UtcNow
) userId
- Строка назначения
- Метка безопасности, если поддерживается
Метод генерирования объединяет все эти данные, преобразует их в байтовый массив и вызывает защитник внутри для защиты / шифрования полезной нагрузки. Наконец, полезная нагрузка преобразуется в строку base 64.
Как получить идентификатор пользователя
Чтобы получить userId
из токена, вам необходимо выполнить обратную инженерию:
- Преобразование токена из строки base 64 обратно в байтовый массив
- Вызов защитника внутри для снятия защиты / дешифрования байтового массива
- Считывание метки времени Ut c
- Чтение
userId
Сложность здесь в том, как получить тот же DataProtector
, используемый для генерации этих токенов!
Как получить Data Protector по умолчанию
Поскольку по умолчанию DataProtectorTokenProvider
встроено в конвейер, я могу думать только о том, чтобы получить то же самое DataProtector
, - это использовать DataProtectorTokenProvider
по умолчанию, чтобы создать протектор с таким же имя по умолчанию «DataProtectorTokenProvider», используемое для генерации токенов!
public class GetResetPasswordViewModelHandler : IRequestHandler<...>
{
...
private readonly IDataProtector _dataProtector;
public GetResetPasswordViewModelHandler(...,
IDataProtectionProvider dataProtectionProvider)
{
...
_dataProtector = dataProtectionProvider.CreateProtector("DataProtectorTokenProvider");
// OR
// dataProtectionProvider.CreateProtector(new DataProtectionTokenProviderOptions().Name);
}
public async Task<ResetPasswordViewModel> Handle(GetResetPasswordViewModel query, ...)
{
// The password reset token comes from query.ResetToken
var resetTokenArray = Convert.FromBase64String(query.ResetToken);
var unprotectedResetTokenArray = _dataProtector.Unprotect(resetTokenArray);
using (var ms = new MemoryStream(unprotectedResetTokenArray))
{
using (var reader = new BinaryReader(ms))
{
// Read off the creation UTC timestamp
reader.ReadInt64();
// Then you can read the userId!
var userId = reader.ReadString();
...
}
}
...
}
}
Снимок экрана:
Мои 2 цента
Кажется, что это большая работа, просто попробуйте прочитать userId
с токена сброса пароля. Я понимаю, что ваш руководитель группы, вероятно, не хочет показывать идентификатор пользователя в ссылке для сброса пароля, или (с) он считает, что это избыточно, поскольку маркер сброса имеет userId
.
Если вы используете целое число, представляющее userId
, и не хочу выставлять это для публикации c, я бы изменил его на GUID
.
Если вам нужно использовать целое число в качестве userId
, я бы просто создайте столбец типа unique_identifier из профиля пользователя (я бы назвал его PublicToken) и используйте его для идентификации пользователя для всех важных вопросов.
var callbackUrl = Url.Action("resetPassword", "account", new
{
area = "",
rt = passwordResetToken, // reset token
ut = appUser.Id // user token, use GUID user id or appUser.PublicToken
}, protocol: Request.Scheme);