다음을 통해 공유


ASP.NET ID를 사용하여 계정 확인 및 암호 복구(C#)

이 자습서를 수행하기 전에 먼저 로그인, 이메일 확인 및 암호 재설정을 사용하여 보안 ASP.NET MVC 5 웹앱 만들기를 완료해야 합니다. 이 자습서에는 자세한 내용이 포함되어 있으며 로컬 계정 확인을 위해 전자 메일을 설정하고 사용자가 ASP.NET ID에서 잊어버린 암호를 재설정할 수 있도록 하는 방법을 보여 줍니다.

로컬 사용자 계정을 사용하려면 사용자가 계정에 대한 암호를 만들어야 하며 해당 암호는 웹앱에 안전하게 저장됩니다. ASP.NET ID는 사용자가 앱에 대한 암호를 만들 필요가 없는 소셜 계정도 지원합니다. 소셜 계정은 타사(예: Google, Twitter, Facebook 또는 Microsoft)를 사용하여 사용자를 인증합니다. 이 항목에서는 다음에 대해 설명합니다.

새 사용자는 로컬 계정을 만드는 전자 메일 별칭을 등록합니다.

계정 등록 창의 이미지

등록 단추를 선택하면 유효성 검사 토큰이 포함된 확인 전자 메일이 해당 전자 메일 주소로 전송됩니다.

전자 메일 전송 확인을 보여 주는 이미지

사용자는 계정에 대한 확인 토큰이 포함된 이메일을 보냅니다.

확인 토큰 이미지

링크를 선택하면 계정이 확인됩니다.

전자 메일 주소를 확인하는 이미지

암호 복구/재설정

암호를 잊어버린 로컬 사용자는 이메일 계정으로 보안 토큰을 전송하여 암호를 재설정할 수 있습니다.

암호 재설정을 잊어버린 창 이미지

사용자는 곧 암호를 재설정할 수 있는 링크가 포함된 이메일을 받게 됩니다.

암호 재설정 전자 메일을 보여 주는 이미지
링크를 선택하면 다시 설정 페이지로 이동합니다.

사용자 암호 재설정 창을 보여 주는 이미지

재설정 단추를 선택하면 암호가 재설정되었는지 확인합니다.

암호 재설정 확인을 보여 주는 이미지

ASP.NET 웹앱 만들기

먼저 Visual Studio 2017을 설치하고 실행합니다.

  1. 새 ASP.NET 웹 프로젝트를 만들고 MVC 템플릿을 선택합니다. Web Forms ASP.NET ID도 지원하므로 웹 양식 앱에서 비슷한 단계를 수행할 수 있습니다.

  2. 인증을 개별 사용자 계정으로 변경합니다.

  3. 앱을 실행하고 등록 링크를 선택하고 사용자를 등록합니다. 이 시점에서 전자 메일의 유일한 유효성 검사는 [EmailAddress] 특성을 사용하는 것입니다.

  4. 서버 Explorer 데이터 연결\DefaultConnection\Tables\AspNetUsers로 이동하고 마우스 오른쪽 단추를 클릭하고 테이블 정의 열기를 선택합니다.

    다음 이미지는 스키마를 AspNetUsers 보여줍니다.

    s p Net 사용자 스키마를 보여 주는 이미지

  5. AspNetUsers 테이블을 마우스 오른쪽 단추로 클릭하고 테이블 데이터 표시를 선택합니다.

    테이블 데이터를 보여 주는 이미지

    이 시점에서 이메일이 확인되지 않았습니다.

ASP.NET Identity의 기본 데이터 저장소는 Entity Framework이지만 다른 데이터 저장소를 사용하고 필드를 추가하도록 구성할 수 있습니다. 이 자습서의 끝에 있는 추가 리소스 섹션을 참조하세요.

OWIN 시작 클래스(Startup.cs)는 앱이 시작되고 OWIN 파이프라인을 구성하고 ASP.NET ID를 초기화하는 App_Start\Startup.Auth.cs에서 메서드를 호출 ConfigureAuth 할 때 호출됩니다. ConfigureAuth 메서드를 검사합니다. 각 CreatePerOwinContext 호출은 지정된 형식의 instance 만들기 위해 요청당 한 번 호출되는 콜백(에 저장OwinContext됨)을 등록합니다. 각 형식(ApplicationDbContext, ApplicationUserManager)의 생성자 및 Create 메서드에서 중단점을 설정하고 각 요청에 대해 호출되는지 확인할 수 있습니다. 및 ApplicationUserManagerApplicationDbContext instance 애플리케이션 전체에서 액세스할 수 있는 OWIN 컨텍스트에 저장됩니다. ASP.NET ID는 쿠키 미들웨어를 통해 OWIN 파이프라인에 연결됩니다. 자세한 내용은 ASP.NET ID의 UserManager 클래스에 대한 요청 수명별 관리를 참조하세요.

보안 프로필을 변경하면 새 보안 스탬프가 생성되고 AspNetUsers 테이블의 필드에 저장됩니다SecurityStamp. SecurityStamp 필드는 보안 쿠키와 다릅니다. 보안 쿠키는 테이블(또는 ID DB의 다른 위치)에 저장 AspNetUsers 되지 않습니다. 보안 쿠키 토큰은 DPAPI 를 사용하여 자체 서명되며 및 만료 시간 정보를 사용하여 UserId, SecurityStamp 만들어집니다.

쿠키 미들웨어는 각 요청에서 쿠키를 확인합니다. 클래스의 Startup 메서드는 SecurityStampValidator DB에 도달하고 에 지정된 대로 보안 스탬프를 validateInterval주기적으로 확인합니다. 이는 보안 프로필을 변경하지 않는 한 30분마다(샘플에서) 발생합니다. 데이터베이스로의 여행을 최소화하기 위해 30분 간격이 선택되었습니다. 자세한 내용은 2단계 인증 자습서 를 참조하세요.

코드의 주석에 따라 메서드는 UseCookieAuthentication 쿠키 인증을 지원합니다. 필드 및 연결된 코드는 SecurityStamp 앱에 추가 보안 계층을 제공합니다. 암호를 변경하면 로그인한 브라우저에서 로그아웃됩니다. 메서드 SecurityStampValidator.OnValidateIdentity 를 사용하면 사용자가 로그인할 때 앱에서 보안 토큰의 유효성을 검사할 수 있으며, 이 토큰은 암호를 변경하거나 외부 로그인을 사용할 때 사용됩니다. 이는 이전 암호로 생성된 토큰(쿠키)이 무효화되도록 하는 데 필요합니다. 샘플 프로젝트에서 사용자 암호를 변경하면 사용자에 대한 새 토큰이 생성되고 이전 토큰이 무효화되고 필드가 SecurityStamp 업데이트됩니다.

ID 시스템을 사용하면 사용자 보안 프로필이 변경될 때(예: 사용자가 암호를 변경하거나 연결된 로그인(예: Facebook, Google, Microsoft 계정 등)을 변경할 때 사용자가 모든 브라우저 인스턴스에서 로그아웃되도록 앱을 구성할 수 있습니다. 예를 들어 아래 이미지는 사용자가 하나의 단추를 선택하여 모든 브라우저 인스턴스(이 경우 IE, Firefox 및 Chrome)에서 로그아웃할 수 있도록 하는 Single Signout 샘플 앱을 보여 줍니다. 또는 샘플을 사용하면 특정 브라우저 instance 로그아웃할 수 있습니다.

Single Sign-Out 샘플 앱 창을 보여 주는 이미지

Single Signout 샘플 앱은 id를 ASP.NET 보안 토큰을 다시 생성할 수 있는 방법을 보여 줍니다. 이는 이전 암호로 생성된 토큰(쿠키)이 무효화되도록 하는 데 필요합니다. 이 기능은 애플리케이션에 추가 보안 계층을 제공합니다. 암호를 변경하면 이 애플리케이션에 로그인한 위치에 로그아웃됩니다.

App_Start\IdentityConfig.cs 파일에는 및 EmailServiceSmsService 클래스가 ApplicationUserManager포함됩니다. 및 SmsService 클래스는 EmailService 각각 인터페이스를 IIdentityMessageService 구현하므로 각 클래스에 메일 및 SMS를 구성하는 공통 메서드가 있습니다. 이 자습서에서는 SendGrid를 통해 전자 메일 알림을 추가하는 방법만 보여 주지만 SMTP 및 기타 메커니즘을 사용하여 전자 메일을 보낼 수 있습니다.

클래스에는 Startup 소셜 로그인(Facebook, Twitter 등)을 추가하는 보일러 플레이트도 포함되어 있습니다. 자세한 내용은 Facebook, Twitter, LinkedIn 및 Google OAuth2 로그온이 포함된 내 자습서 MVC 5 앱을 참조하세요.

ApplicationUserManager 사용자 ID 정보를 포함하고 다음 기능을 구성하는 클래스를 검사합니다.

  • 암호 강도 요구 사항.
  • 사용자 잠금(시도 및 시간).
  • 2FA(2단계 인증). 다른 자습서에서 2FA 및 SMS를 다룹니다.
  • 전자 메일 및 SMS 서비스를 연결합니다. (다른 자습서에서 SMS를 다루겠습니다).

클래스는 ApplicationUserManager 제네릭 UserManager<ApplicationUser> 클래스에서 파생됩니다. ApplicationUserIdentityUser에서 파생됩니다. IdentityUser 는 제네릭 IdentityUser 클래스에서 파생됩니다.

//     Default EntityFramework IUser implementation
public class IdentityUser<TKey, TLogin, TRole, TClaim> : IUser<TKey>
   where TLogin : IdentityUserLogin<TKey>
   where TRole : IdentityUserRole<TKey>
   where TClaim : IdentityUserClaim<TKey>
{
   public IdentityUser()
   {
      Claims = new List<TClaim>();
      Roles = new List<TRole>();
      Logins = new List<TLogin>();
   }

   ///     User ID (Primary Key)
   public virtual TKey Id { get; set; }

   public virtual string Email { get; set; }
   public virtual bool EmailConfirmed { get; set; }

   public virtual string PasswordHash { get; set; }

   ///     A random value that should change whenever a users credentials have changed (password changed, login removed)
   public virtual string SecurityStamp { get; set; }

   public virtual string PhoneNumber { get; set; }
   public virtual bool PhoneNumberConfirmed { get; set; }

   public virtual bool TwoFactorEnabled { get; set; }

   ///     DateTime in UTC when lockout ends, any time in the past is considered not locked out.
   public virtual DateTime? LockoutEndDateUtc { get; set; }

   public virtual bool LockoutEnabled { get; set; }

   ///     Used to record failures for the purposes of lockout
   public virtual int AccessFailedCount { get; set; }
   
   ///     Navigation property for user roles
   public virtual ICollection<TRole> Roles { get; private set; }

   ///     Navigation property for user claims
   public virtual ICollection<TClaim> Claims { get; private set; }

   ///     Navigation property for user logins
   public virtual ICollection<TLogin> Logins { get; private set; }
   
   public virtual string UserName { get; set; }
}

위의 속성은 위에 표시된 테이블의 AspNetUsers 속성과 일치합니다.

IUser 제네릭 인수를 사용하면 기본 키에 다른 형식을 사용하여 클래스를 파생할 수 있습니다. 기본 키를 문자열에서 int 또는 GUID로 변경하는 방법을 보여주는 ChangePK 샘플을 참조하세요.

ApplicationUser

ApplicationUser (public class ApplicationUserManager : UserManager<ApplicationUser>)는 Models\IdentityModels.cs 에 다음과 같이 정의됩니다.

public class ApplicationUser : IdentityUser
{
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(
        UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in 
       //   CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, 
    DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here
        return userIdentity;
    }
}

위의 강조 표시된 코드는 ClaimsIdentity를 생성합니다. ASP.NET ID 및 OWIN 쿠키 인증은 클레임 기반이므로 프레임워크는 앱에서 사용자에 대한 을 ClaimsIdentity 생성해야 합니다. ClaimsIdentity 에는 사용자의 이름, 연령 및 사용자가 속한 역할과 같은 사용자에 대한 모든 클레임에 대한 정보가 있습니다. 이 단계에서 사용자에 대한 클레임을 더 추가할 수도 있습니다.

OWIN AuthenticationManager.SignIn 메서드는 를 ClaimsIdentity 전달하고 사용자에 로그인합니다.

private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
    AuthenticationManager.SignIn(new AuthenticationProperties(){
       IsPersistent = isPersistent }, 
       await user.GenerateUserIdentityAsync(UserManager));
}

Facebook, Twitter, LinkedIn 및 Google OAuth2 로그온을 사용하는 MVC 5 앱 은 클래스에 속성을 ApplicationUser 추가하는 방법을 보여줍니다.

Email 확인

새 사용자가 등록한 전자 메일을 확인하여 다른 사람을 가장하지 않는지 확인하는 것이 좋습니다(즉, 다른 사용자의 전자 메일에 등록되지 않음). 토론 포럼 "bob@example.com""joe@contoso.com"이 있다고 가정해 봅시다. 이메일 확인 없이 앱 "joe@contoso.com" 에서 원치 않는 전자 메일을 받을 수 있습니다. Bob이 실수로 로 등록되어 "bib@example.com" 눈치채지 못했다고 가정해 보겠습니다. 앱에 올바른 전자 메일이 없기 때문에 암호 복구를 사용할 수 없습니다. Email 확인은 봇으로부터 제한된 보호만 제공하고 결정된 스팸으로부터 보호를 제공하지 않으며 등록에 사용할 수 있는 많은 작업 중인 이메일 별칭이 있습니다. 아래 샘플에서 사용자는 자신의 계정이 확인될 때까지 암호를 변경할 수 없습니다(등록한 전자 메일 계정에서 받은 확인 링크를 선택하여). 이 작업 흐름을 다른 시나리오에 적용할 수 있습니다. 예를 들어 관리자가 만든 새 계정에서 암호를 확인하고 재설정하는 링크를 보내고, 프로필을 변경한 경우 사용자에게 전자 메일을 보낼 수 있습니다. 일반적으로 새 사용자가 전자 메일, SMS 문자 메시지 또는 다른 메커니즘으로 확인되기 전에 웹 사이트에 데이터를 게시하지 못하도록 방지하려고 합니다.

보다 완전한 샘플 빌드

이 섹션에서는 NuGet을 사용하여 작업할 보다 완전한 샘플을 다운로드합니다.

  1. 새 빈 ASP.NET 웹 프로젝트를 만듭니다.

  2. 패키지 관리자 콘솔에서 다음 명령을 입력합니다.

    Install-Package SendGrid
    Install-Package -Prerelease Microsoft.AspNet.Identity.Samples
    

    이 자습서에서는 SendGrid 를 사용하여 이메일을 보냅니다. 패키지는 Identity.Samples 작업할 코드를 설치합니다.

  3. SSL을 사용하도록 프로젝트를 설정합니다.

  4. 앱을 실행하고, 등록 링크를 선택하고, 등록 양식을 게시하여 로컬 계정 만들기를 테스트합니다.

  5. 이메일 확인을 시뮬레이션하는 데모 이메일 링크를 선택합니다.

  6. 샘플(계정 컨트롤러의 코드) ViewBag.Link 에서 데모 이메일 링크 확인 코드를 제거합니다. DisplayEmailForgotPasswordConfirmation 작업 메서드 및 razor 보기 )를 참조하세요.

경고

이 샘플의 보안 설정을 변경하는 경우 프로덕션 앱은 변경 내용을 명시적으로 호출하는 보안 감사를 받아야 합니다.

App_Start\IdentityConfig.cs에서 코드 검사

이 샘플에서는 계정을 만들고 관리 역할에 추가하는 방법을 보여줍니다. 샘플의 전자 메일을 관리자 계정에 사용할 전자 메일로 바꿔야 합니다. 지금 관리자 계정을 만드는 가장 쉬운 방법은 메서드에서 프로그래밍 방식으로 수행됩니다 Seed . 앞으로 사용자 및 역할을 만들고 관리할 수 있는 도구를 사용할 수 있기를 바랍니다. 샘플 코드를 사용하면 사용자 및 역할을 만들고 관리할 수 있지만 먼저 역할 및 사용자 관리자 페이지를 실행하려면 관리자 계정이 있어야 합니다. 이 샘플에서는 DB를 시드할 때 관리자 계정이 만들어집니다.

암호를 변경하고 이름을 메일 알림 받을 수 있는 계정으로 변경합니다.

경고

보안 - 소스 코드에 중요한 데이터를 저장하지 않습니다.

앞에서 app.CreatePerOwinContext 설명한 것처럼 시작 클래스의 호출은 앱 DB 콘텐츠, 사용자 관리자 및 역할 관리자 클래스의 메서드에 콜백 Create 을 추가합니다. OWIN 파이프라인은 각 요청에 대해 이러한 클래스에서 메서드를 호출 Create 하고 각 클래스에 대한 컨텍스트를 저장합니다. 계정 컨트롤러는 HTTP 컨텍스트(OWIN 컨텍스트 포함)에서 사용자 관리자를 노출합니다.

public ApplicationUserManager UserManager
{
    get
    {
        return _userManager ?? 
    HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
    }
    private set
    {
        _userManager = value;
    }
}

사용자가 로컬 계정을 등록하면 메서드가 HTTP Post Register 호출됩니다.

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
        var result = await UserManager.CreateAsync(user, model.Password);
        if (result.Succeeded)
        {
            var code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
            var callbackUrl = Url.Action(
               "ConfirmEmail", "Account", 
               new { userId = user.Id, code = code }, 
               protocol: Request.Url.Scheme);

            await UserManager.SendEmailAsync(user.Id, 
               "Confirm your account", 
               "Please confirm your account by clicking this link: <a href=\"" 
                                               + callbackUrl + "\">link</a>");
            // ViewBag.Link = callbackUrl;   // Used only for initial demo.
            return View("DisplayEmail");
        }
        AddErrors(result);
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}

위의 코드는 모델 데이터를 사용하여 입력한 이메일 및 암호를 사용하여 새 사용자 계정을 만듭니다. 이메일 별칭이 데이터 저장소에 있으면 계정 만들기가 실패하고 양식이 다시 표시됩니다. 메서드는 GenerateEmailConfirmationTokenAsync 보안 확인 토큰을 만들고 ASP.NET ID 데이터 저장소에 저장합니다. Url.Action 메서드는 및 확인 토큰이 UserId 포함된 링크를 만듭니다. 그러면 이 링크가 사용자에게 전자 메일로 보내집니다. 사용자는 전자 메일 앱의 링크를 선택하여 계정을 확인할 수 있습니다.

전자 메일 확인 설정

SendGrid 등록 페이지로 이동하여 무료 계정에 등록합니다. 다음과 유사한 코드를 추가하여 SendGrid를 구성합니다.

public class EmailService : IIdentityMessageService
{
   public Task SendAsync(IdentityMessage message)
   {
      return configSendGridasync(message);
   }

   private Task configSendGridasync(IdentityMessage message)
   {
      var myMessage = new SendGridMessage();
      myMessage.AddTo(message.Destination);
      myMessage.From = new System.Net.Mail.MailAddress(
                          "Joe@contoso.com", "Joe S.");
      myMessage.Subject = message.Subject;
      myMessage.Text = message.Body;
      myMessage.Html = message.Body;

      var credentials = new NetworkCredential(
                 ConfigurationManager.AppSettings["mailAccount"],
                 ConfigurationManager.AppSettings["mailPassword"]
                 );

      // Create a Web transport for sending email.
      var transportWeb = new Web(credentials);

      // Send the email.
      if (transportWeb != null)
      {
         return transportWeb.DeliverAsync(myMessage);
      }
      else
      {
         return Task.FromResult(0);
      }
   }
}

참고

Email 클라이언트는 문자 메시지만 자주 수락합니다(HTML 없음). 텍스트 및 HTML로 메시지를 제공해야 합니다. 위의 SendGrid 샘플에서 이 작업은 위에 표시된 및 myMessage.Html 코드로 myMessage.Text 수행됩니다.

다음 코드에서는 MailMessage 클래스를 사용하여 전자 메일을 보내는 방법을 보여 줍니다. 여기서 message.Body 링크만 반환합니다.

void sendMail(Message message)
{
#region formatter
   string text = string.Format("Please click on this link to {0}: {1}", message.Subject, message.Body);
   string html = "Please confirm your account by clicking this link: <a href=\"" + message.Body + "\">link</a><br/>";

   html += HttpUtility.HtmlEncode(@"Or click on the copy the following link on the browser:" + message.Body);
#endregion

   MailMessage msg = new MailMessage();
   msg.From = new MailAddress("joe@contoso.com");
   msg.To.Add(new MailAddress(message.Destination));
   msg.Subject = message.Subject;
   msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(text, null, MediaTypeNames.Text.Plain));
   msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(html, null, MediaTypeNames.Text.Html));

   SmtpClient smtpClient = new SmtpClient("smtp.gmail.com", Convert.ToInt32(587));
   System.Net.NetworkCredential credentials = new System.Net.NetworkCredential("joe@contoso.com", "XXXXXX");
   smtpClient.Credentials = credentials;
   smtpClient.EnableSsl = true;
   smtpClient.Send(msg);
}

경고

보안 - 소스 코드에 중요한 데이터를 저장하지 않습니다. 계정 및 자격 증명은 appSetting에 저장됩니다. Azure에서는 Azure Portal 구성 탭에 이러한 값을 안전하게 저장할 수 있습니다. ASP.NET 및 Azure에 암호 및 기타 중요한 데이터를 배포하는 모범 사례를 참조하세요.

SendGrid 자격 증명을 입력하고, 앱을 실행하고, 이메일 별칭으로 등록하면 전자 메일에서 확인 링크를 선택할 수 있습니다. Outlook.com 전자 메일 계정으로 이 작업을 수행하는 방법을 보려면 Outlook.ComSMTP 호스트용 John Atten의 C# SMTP 구성 및 ASP.NETID 2.0: 계정 유효성 검사 설정 및 권한 부여 게시물 Two-Factor 참조하세요.

사용자가 등록 단추를 선택하면 유효성 검사 토큰이 포함된 확인 전자 메일이 전자 메일 주소로 전송됩니다.

전자 메일 전송 확인 창 이미지

사용자는 계정에 대한 확인 토큰이 포함된 이메일을 보냅니다.

받은 전자 메일 이미지

코드 검사

다음 코드는 POST ForgotPassword 메서드를 보여 줍니다.

public async Task<ActionResult> ForgotPassword(ForgotPasswordViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = await UserManager.FindByNameAsync(model.Email);
        if (user == null || !(await UserManager.IsEmailConfirmedAsync(user.Id)))
        {
            // Don't reveal that the user does not exist or is not confirmed
            return View("ForgotPasswordConfirmation");
        }

        var code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
        var callbackUrl = Url.Action("ResetPassword", "Account", 
    new { UserId = user.Id, code = code }, protocol: Request.Url.Scheme);
        await UserManager.SendEmailAsync(user.Id, "Reset Password", 
    "Please reset your password by clicking here: <a href=\"" + callbackUrl + "\">link</a>");        
        return View("ForgotPasswordConfirmation");
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}

사용자 전자 메일이 확인되지 않으면 메서드가 자동으로 실패합니다. 잘못된 이메일 주소에 대한 오류가 게시된 경우 악의적인 사용자는 해당 정보를 사용하여 공격할 유효한 userId(이메일 별칭)를 찾을 수 있습니다.

다음 코드는 사용자가 보낸 전자 메일에서 확인 링크를 선택할 때 호출되는 계정 컨트롤러의 메서드를 보여 ConfirmEmail 줍니다.

public async Task<ActionResult> ConfirmEmail(string userId, string code)
{
    if (userId == null || code == null)
    {
        return View("Error");
    }
    var result = await UserManager.ConfirmEmailAsync(userId, code);
    if (result.Succeeded)
    {
        return View("ConfirmEmail");
    }
    AddErrors(result);
    return View();
}

잊어버린 암호 토큰이 사용되면 무효화됩니다. 메서드의 Create 다음 코드 변경( App_Start\IdentityConfig.cs 파일)은 토큰이 3시간 내에 만료되도록 설정합니다.

if (dataProtectionProvider != null)
 {
    manager.UserTokenProvider =
       new DataProtectorTokenProvider<ApplicationUser>
          (dataProtectionProvider.Create("ASP.NET Identity"))
          {                    
             TokenLifespan = TimeSpan.FromHours(3)
          };
 }

위의 코드를 사용하면 잊어버린 암호와 이메일 확인 토큰이 3시간 후에 만료됩니다. 기본값 TokenLifespan 은 1일입니다.

다음 코드는 이메일 확인 방법을 보여줍니다.

// GET: /Account/ConfirmEmail
[AllowAnonymous]
public async Task<ActionResult> ConfirmEmail(string userId, string code)
{
   if (userId == null || code == null)
   {
      return View("Error");
   }
   IdentityResult result;
   try
   {
      result = await UserManager.ConfirmEmailAsync(userId, code);
   }
   catch (InvalidOperationException ioe)
   {
      // ConfirmEmailAsync throws when the userId is not found.
      ViewBag.errorMessage = ioe.Message;
      return View("Error");
   }

   if (result.Succeeded)
   {
      return View();
   }

   // If we got this far, something failed.
   AddErrors(result);
   ViewBag.errorMessage = "ConfirmEmail failed";
   return View("Error");
}

앱을 더 안전하게 만들기 위해 ASP.NET ID는 Two-Factor 인증(2FA)을 지원합니다. ASP.NET ID 2.0: 계정 유효성 검사 설정 및 John Atten의 권한 부여 Two-Factor 참조하세요. 로그인 암호 시도 실패 시 계정 잠금을 설정할 수 있지만 이 방법을 사용하면 로그인이 DOS 잠금에 취약해집니다. 2FA에서만 계정 잠금을 사용하는 것이 좋습니다.

추가 리소스