Asp net Core Identity token истечение срока аутентификации - PullRequest
0 голосов
/ 27 августа 2018

Я использую Asp Net Core Identity.Это то, что я пытаюсь сделать, и я понятия не имею, как это сделать, поэтому мне нужна помощь специалиста по этому вопросу.Когда новый пользователь регистрируется в моем приложении, на его электронную почту отправляется ссылка для сброса пароля. Теперь, когда срок действия токена ссылки в ссылке истек, и пользователь нажимает на ссылку, мне нужно показать сообщение с истекшим токеном.Как я могу узнать, истек ли токен, когда пользователь нажимает на ссылку, которая находится в электронном письме.Кто-нибудь может предложить пути достижения этого сценария?

1 Ответ

0 голосов
/ 27 августа 2018

ASP.NET Core имеет встроенную систему утверждений для хранения информации о пользователе.

Для этого

  1. добавить вспомогательный метод для сохранения даты и времени истечения в Register.cshtml.cs:

    private async Task AddTokenExpirationInfo(IdentityUser user, int span=1*24*60)
    {
        var expiresAt = DateTime.Now.Add(TimeSpan.FromMinutes(span));
        var tokenExpiredAtClaim = new Claim("ActivtationTokenExpiredAt", expiresAt.ToUniversalTime().Ticks.ToString());
        await _userManager.AddClaimAsync(user, tokenExpiredAtClaim);
    }
    
  2. добавить вспомогательный метод, чтобы проверить, не истек ли токен в ConfirmEmail.cshtml.cs:

    private async Task<bool> TokenExpiredValidate(IdentityUser user) {
        var claims = (await _userManager.GetClaimsAsync(user))
            .Where(c => c.Type == "ActivtationTokenExpiredAt");
        var expiredAt = claims.FirstOrDefault()?.Value;
        bool expired = true;    // default value
        if (expiredAt != null)
        {
            var expires = Convert.ToInt64(expiredAt);
            var now = DateTime.Now.Ticks;
            expired= now <= expires? false : true;
        }
        else {
            expired = false;
        }
        // clear claims
        await _userManager.RemoveClaimsAsync(user, claims);
        return expired;
    }
    
  3. , вызывать AddTokenExpirationInfo при запросе на регистрацию:

    public async Task<IActionResult> OnPostAsync(string returnUrl = null)
    {
        returnUrl = returnUrl ?? Url.Content("~/");
        if (ModelState.IsValid)
        {
            var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
            var result = await _userManager.CreateAsync(user, Input.Password);
            if (result.Succeeded)
            {
                _logger.LogInformation("User created a new account with password.");
    
                var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
                var callbackUrl = Url.Page(
                    "/Account/ConfirmEmail",
                    pageHandler: null,
                    values: new { userId = user.Id, code = code },
                    protocol: Request.Scheme);
    
                await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
                    $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
    
                ///////////////// invoke here  ////////////////////
                AddTokenExpirationInfo(user);
    
                await _signInManager.SignInAsync(user, isPersistent: false);
                return LocalRedirect(returnUrl);
            }
            foreach (var error in result.Errors)
            {
                ModelState.AddModelError(string.Empty, error.Description);
            }
        }
    
        // If we got this far, something failed, redisplay form
        return Page();
    }
    
  4. вызывает TokenExpiredValidate в вашем ConfirmEmail.cshtml.cs:

    public async Task<IActionResult> OnGetAsync(string userId, string code)
    {
        if (userId == null || code == null)
        {
            return RedirectToPage("/Index");
        }
    
        var user = await _userManager.FindByIdAsync(userId);
        if (user == null)
        {
            return NotFound($"Unable to load user with ID '{userId}'.");
        }
        var result = await _userManager.ConfirmEmailAsync(user, code);
        if (!result.Succeeded)
        {
            throw new InvalidOperationException($"Error confirming email for user with ID '{userId}':");
        }
        if (await TokenExpiredValidate(user)) 
            throw new InvalidOperationException($"Token has alread expired '{userId}':");
    
        return Page();
    }
    

Когда пользователь зарегистрируется, в таблице AspNetUserClaims будет запись:

Demo

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

...