계정 확인 및 ASP.NET 코어에서 암호 복구Account confirmation and password recovery in ASP.NET Core

작성자: Rick AndersonBy Rick Anderson

이 자습서에서는 전자 메일 확인 및 암호 재설정으로 ASP.NET Core 응용 프로그램을 구축 하는 방법을 보여 줍니다.This tutorial shows you how to build an ASP.NET Core app with email confirmation and password reset.

새 ASP.NET Core 프로젝트 만들기Create a New ASP.NET Core Project

이 단계는 Windows에서 Visual Studio에 적용 됩니다.This step applies to Visual Studio on Windows. CLI 지침은 다음 섹션을 참조 하십시오.See the next section for CLI instructions.

이 자습서는 Visual Studio 2017 미리 보기 2 이상이 필요합니다.The tutorial requires Visual Studio 2017 Preview 2 or later.

  • Visual Studio에서 새 웹 응용 프로그램 프로젝트를 만듭니다.In Visual Studio, create a New Web Application Project.
  • 선택 ASP.NET Core 2.0합니다.Select ASP.NET Core 2.0. 다음 그림 표시 .NET Core 선택 하면 선택할 수 있지만 .NET Framework합니다.The following image show .NET Core selected, but you can select .NET Framework.
  • 선택 인증 변경 로 설정 하 고 개별 사용자 계정합니다.Select Change Authentication and set to Individual User Accounts.
  • 기본값을 그대로 두고 저장 된 사용자 계정 앱에서합니다.Keep the default Store user accounts in-app.

선택 하는 "개별 사용자 계정 radio"를 표시 하는 새 프로젝트 대화 상자

MacOS 및 Linux 용.NET core CLI 프로젝트 만들기.NET Core CLI project creation for macOS and Linux

CLI 또는 SQLite를 사용 하는 경우 명령 창에서 다음을 실행 합니다.If you're using the CLI or SQLite, run the following in a command window:

dotnet new mvc --auth Individual
  • --auth Individual개별 사용자 계정 템플릿을 지정합니다.--auth Individual specifies the Individual User Accounts template.
  • Windows에서 추가 된 -uld 옵션입니다.On Windows, add the -uld option. -uld 옵션은 SQLite DB 보다는 LocalDB 연결 문자열을 만듭니다.The -uld option creates a LocalDB connection string rather than a SQLite DB.
  • 실행 new mvc --help 도움말을 보려면이 명령에 있습니다.Run new mvc --help to get help on this command.

새 사용자 등록을 테스트 합니다.Test new user registration

응용 프로그램을 실행, 선택는 등록 링크를 선택한 사용자를 등록 합니다.Run the app, select the Register link, and register a user. Entity Framework Core 마이그레이션을 실행 하는 지침을 따릅니다.Follow the instructions to run Entity Framework Core migrations. 전자 메일에만 유효성 검사와는 시점에서 [EmailAddress] 특성입니다.At this point, the only validation on the email is with the [EmailAddress] attribute. 등록을 제출 하면 앱에 로그인 되어 있습니다.After you submit the registration, you are logged into the app. 자습서의 뒷부분에 나오는 변경 합니다이 있으므로 새 사용자가 전자 메일의 유효성을 검사 될 때까지 로그인 할 수 없습니다.Later in the tutorial, we'll change this so new users cannot log in until their email has been validated.

Id 데이터베이스 보기View the Identity database

  • 보기 메뉴 선택 SQL Server 개체 탐색기 (SSOX).From the View menu, select SQL Server Object Explorer (SSOX).
  • 로 이동 (localdb) (SQL Server 13) MSSQLLocalDB합니다.Navigate to (localdb)MSSQLLocalDB(SQL Server 13). 마우스 오른쪽 단추로 클릭 dbo입니다. AspNetUsers > 데이터를 볼:Right-click on dbo.AspNetUsers > View Data:

SQL Server 개체 탐색기의 AspNetUsers 테이블에 대 한 상황에 맞는 메뉴

참고는 EmailConfirmed 필드는 False합니다.Note the EmailConfirmed field is False.

응용 프로그램에서 확인 전자 메일을 보낼 때 다음 단계에서이 전자 메일에 다시 사용 수 있습니다.You might want to use this email again in the next step when the app sends a confirmation email. 선택한 행을 마우스 오른쪽 단추로 클릭 삭제합니다.Right-click on the row and select Delete. 전자 메일을 지금 별칭 삭제는 간편한 방법이 다음 단계에 있습니다.Deleting the email alias now will make it easier in the following steps.

Ssl을 사용 하 여 SSL에 대 한 IIS Express를 설치합니다Require SSL and setup IIS Express for SSL

참조 SSL 적용합니다.See Enforcing SSL.

전자 메일 확인이 필요Require email confirmation

다른 사용자에 가장 하지 않는 것을 확인 하려면 새 사용자 등록의 전자 메일을 확인 하는 것이 좋습니다 (즉, 이러한 하지 않은 등록 된 다른 사용자의 전자 메일).It's a best practice to confirm the email of a new user registration to verify they are not impersonating someone else (that is, they haven't registered with someone else's email). 토론 포럼을 가지 며 하지 못하도록 하려는 경우를 가정해 볼 "yli@example.com로 등록" 에서"nolivetto@contoso.com."Suppose you had a discussion forum, and you wanted to prevent "yli@example.com" from registering as "nolivetto@contoso.com." 전자 메일 확인 하지 않고 "nolivetto@contoso.com" 응용 프로그램에서 원치 않는 전자 메일을 가져올 수 있습니다.Without email confirmation, "nolivetto@contoso.com" could get unwanted email from your app. 사용자는 실수로으로 등록 된다고 가정 합니다 "ylo@example.com" 맞춤법 오류를 발견 하지 않은 "yli"의 수 앱이 올바른 전자 메일에 없는 때문에 암호 복구를 사용 하도록 합니다.Suppose the user accidentally registered as "ylo@example.com" and hadn't noticed the misspelling of "yli," they wouldn't be able to use password recovery because the app doesn't have their correct email. 전자 메일 확인 bot에서만 제한 된 보호를 제공 하 고 여러 작업 전자 메일 별칭을 등록 하는 데 사용할 수 있는 결정된 된 스팸에서 보호를 제공 하지 않습니다.Email confirmation provides only limited protection from bots and doesn't provide protection from determined spammers who have many working email aliases they can use to register.

일반적으로 새 사용자는 확인 된 전자 메일을 갖기 전에 웹 사이트에 데이터를 게시 하는 것을 방지 하려고 합니다.You generally want to prevent new users from posting any data to your web site before they have a confirmed email.

업데이트 ConfigureServices 확인 된 전자 메일을 요구 하도록 합니다.Update ConfigureServices to require a confirmed email:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
      options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddIdentity<ApplicationUser, IdentityRole>(config =>
        {
            config.SignIn.RequireConfirmedEmail = true;
        })
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    // Add application services.
    services.AddTransient<IEmailSender, EmailSender>();

    services.AddMvc();

    services.Configure<AuthMessageSenderOptions>(Configuration);
}
config.SignIn.RequireConfirmedEmail = true;

이전 줄에는 해당 전자 메일이 확인 될 때까지 로그인에서 등록 된 사용자 수 없습니다.The preceding line prevents registered users from being logged in until their email is confirmed. 그러나 해당 줄에서 등록 한 후에 기록 되 고 새 사용자를 방해 되지는 않습니다.However, that line does not prevent new users from being logged in after they register. 기본 코드는 등록 한 후 사용자를 로그인 합니다.The default code logs in a user after they register. 로그 한 후에 다시 등록할 때 까지는 로그인 할 수 없습니다.Once they log out, they won't be able to log in again until they register. 따라서 새로 등록 된 사용자는 이번에 변경 하는 자습서의 뒷부분에 나오는 하지 에 기록 합니다.Later in the tutorial we'll change the code so newly registered user are not logged in.

전자 메일 공급자를 구성 합니다.Configure email provider

이 자습서에서는 SendGrid 전자 메일을 보내는 데 사용 됩니다.In this tutorial, SendGrid is used to send email. SendGrid 계정 및 전자 메일을 보내는 키 필요.You need a SendGrid account and key to send email. 다른 전자 메일 공급자를 사용할 수 있습니다.You can use other email providers. ASP.NET Core 2.x 포함 System.Net.Mail, 응용 프로그램에서 전자 메일을 보낼 수 있습니다.ASP.NET Core 2.x includes System.Net.Mail, which allows you to send email from your app. 전자 메일을 보내는 SendGrid 또는 다른 전자 메일 서비스를 사용 하는 것이 좋습니다.We recommend you use SendGrid or another email service to send email.

옵션 패턴 사용자 계정 및 키 설정에 액세스 하는 데 사용 됩니다.The Options pattern is used to access the user account and key settings. 자세한 내용은 참조 구성합니다.For more information, see configuration.

전자 메일 보안 키를 인출 하는 클래스를 만듭니다.Create a class to fetch the secure email key. 이 샘플은 AuthMessageSenderOptions 클래스에 만들어집니다는 Services/AuthMessageSenderOptions.cs 파일입니다.For this sample, the AuthMessageSenderOptions class is created in the Services/AuthMessageSenderOptions.cs file.

public class AuthMessageSenderOptions
{
    public string SendGridUser { get; set; }
    public string SendGridKey { get; set; }
}

설정의 SendGridUserSendGridKey암호 관리자 도구합니다.Set the SendGridUser and SendGridKey with the secret-manager tool. 예:For example:

C:\WebAppl\src\WebApp1>dotnet user-secrets set SendGridUser RickAndMSFT
info: Successfully saved SendGridUser = RickAndMSFT to the secret store.

암호 관리자 windows에서의 사용자 키/값 쌍을 저장 한 secrets.json %APPDATA%/Microsoft/UserSecrets/ < WebAppName userSecretsId > 디렉터리에 파일입니다.On Windows, Secret Manager stores your keys/value pairs in a secrets.json file in the %APPDATA%/Microsoft/UserSecrets/ directory.

콘텐츠는 secrets.json 파일 암호화 되지 않습니다.The contents of the secrets.json file are not encrypted. secrets.json 파일은 다음과 같습니다 (의 SendGridKey 값 제거 되었습니다.)The secrets.json file is shown below (the SendGridKey value has been removed.)

{
  "SendGridUser": "RickAndMSFT",
  "SendGridKey": "<key removed>"
}

AuthMessageSenderOptions를 사용 하는 시작 구성Configure startup to use AuthMessageSenderOptions

추가 AuthMessageSenderOptions 끝날 때 서비스 컨테이너에는 ConfigureServices 에서 메서드는 Startup.cs 파일:Add AuthMessageSenderOptions to the service container at the end of the ConfigureServices method in the Startup.cs file:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
      options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddIdentity<ApplicationUser, IdentityRole>(config =>
        {
            config.SignIn.RequireConfirmedEmail = true;
        })
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    // Add application services.
    services.AddTransient<IEmailSender, EmailSender>();

    services.AddMvc();

    services.Configure<AuthMessageSenderOptions>(Configuration);
}

AuthMessageSender 클래스 구성Configure the AuthMessageSender class

이 자습서에서는 통해 전자 메일 알림을 추가 하는 방법을 보여 줍니다. SendGrid, 하지만 SMTP 및 다른 메커니즘을 사용 하 여 메일을 보낼 수 있습니다.This tutorial shows how to add email notifications through SendGrid, but you can send email using SMTP and other mechanisms.

  • 설치는 SendGrid NuGet 패키지 합니다.Install the SendGrid NuGet package. 패키지 관리자 콘솔에서 다음을 입력 다음 명령을:From the Package Manager Console, enter the following the following command:

    Install-Package SendGrid

  • 참조 SendGrid를 무료로 시작 무료 SendGrid 계정을 등록할 수 있습니다.See Get Started with SendGrid for Free to register for a free SendGrid account.

SendGrid를 구성 합니다.Configure SendGrid

  • 에 코드를 추가 Services/EmailSender.cs SendGrid를 구성 하는 다음과 비슷합니다.Add code in Services/EmailSender.cs similar to the following to configure SendGrid:
using Microsoft.Extensions.Options;
using SendGrid;
using SendGrid.Helpers.Mail;
using System.Threading.Tasks;

namespace WebPW.Services
{
    public class EmailSender : IEmailSender
    {
        public EmailSender(IOptions<AuthMessageSenderOptions> optionsAccessor)
        {
            Options = optionsAccessor.Value;
        }

        public AuthMessageSenderOptions Options { get; } //set only via Secret Manager

        public Task SendEmailAsync(string email, string subject, string message)
        {
            return Execute(Options.SendGridKey, subject, message, email);
        }

        public Task Execute(string apiKey, string subject, string message, string email)
        {
            var client = new SendGridClient(apiKey);
            var msg = new SendGridMessage()
            {
                From = new EmailAddress("Joe@contoso.com", "Joe Smith"),
                Subject = subject,
                PlainTextContent = message,
                HtmlContent = message
            };
            msg.AddTo(new EmailAddress(email));
            return client.SendEmailAsync(msg);
        }
    }
}

계정 확인 및 암호 복구 사용Enable account confirmation and password recovery

서식 파일에는 계정 확인 및 암호 복구를 위한 코드가 있습니다.The template has the code for account confirmation and password recovery. 찾을 [HttpPost] Register 에서 메서드는 AccountController.cs 파일입니다.Find the [HttpPost] Register method in the AccountController.cs file.

새로 등록 된 사용자가 있는 다음 줄을 주석 처리에 자동으로 로그온에서 함:Prevent newly registered users from being automatically logged on by commenting out the following line:

await _signInManager.SignInAsync(user, isPersistent: false);

전체 메서드 강조 표시 하는 변경 된 줄으로 표시 됩니다.The complete method is shown with the changed line highlighted:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
{
    ViewData["ReturnUrl"] = returnUrl;
    if (ModelState.IsValid)
    {
        var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
        var result = await _userManager.CreateAsync(user, model.Password);
        if (result.Succeeded)
        {
            _logger.LogInformation("User created a new account with password.");

            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme);
            await _emailSender.SendEmailConfirmationAsync(model.Email, callbackUrl);

            // await _signInManager.SignInAsync(user, isPersistent: false);
            _logger.LogInformation("User created a new account with password.");
            return RedirectToLocal(returnUrl);
        }
        AddErrors(result);
    }

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

등록 전자 메일을 확인 하 고 암호를 다시 설정Register, confirm email, and reset password

웹 응용 프로그램을 실행 하 고 계정 확인 및 암호 복구 흐름을 테스트 합니다.Run the web app, and test the account confirmation and password recovery flow.

  • 응용 프로그램을 실행 하 고 새 사용자 등록Run the app and register a new user

    웹 응용 프로그램 계정 등록 보기

  • 계정 확인 링크에 대 한 전자 메일을 확인 합니다.Check your email for the account confirmation link. 참조 전자 메일을 디버그 전자 메일을 얻지 못한 경우.See Debug email if you don't get the email.

  • 사용자의 전자 메일 확인에 대 한 링크를 클릭 합니다.Click the link to confirm your email.
  • 전자 메일 및 암호를 로그인 합니다.Log in with your email and password.
  • 로그 오프 합니다.Log off.

관리 페이지 보기View the manage page

브라우저에서 자신의 사용자 이름을 선택: 사용자 이름으로 브라우저 창Select your user name in the browser: browser window with user name

사용자 이름을 보려면 탐색 모음을 확장 해야 할 수 있습니다.You might need to expand the navbar to see user name.

탐색 모음

관리 페이지에 표시 됩니다는 프로필 탭이 선택 되어 있습니다.The manage page is displayed with the Profile tab selected. 전자 메일 확인 전자 메일을 나타내는 확인란을 보여 줍니다.The Email shows a check box indicating the email has been confirmed.

관리 페이지

테스트 암호 재설정Test password reset

  • 로그인 되어 있는 경우 선택 로그 아웃합니다.If you're logged in, select Logout.
  • 선택 된 로그인 연결 하 고 선택의 암호를 잊으셨나요? 링크 합니다.Select the Log in link and select the Forgot your password? link.
  • 계정 등록에 사용한 전자 메일을 입력 합니다.Enter the email you used to register the account.
  • 암호를 다시 설정에 대 한 링크가 포함 된 메일이 전송 됩니다.An email with a link to reset your password will be sent. 전자 메일을 확인 하 고 암호를 다시 설정에 대 한 링크를 클릭 합니다.Check your email and click the link to reset your password. 암호가 성공적으로 다시 설정, 전자 메일 및 새 암호 로그인 할 수 있습니다.After your password has been successfully reset, you can login with your email and new password.

전자 메일을 디버그Debug email

전자 메일 작업을 가져올 수 없습니다 하는 경우:If you can't get email working:

참고: 보안 모범 사례는 테스트 및 개발에서 생산 암호를 사용 하지 않도록 합니다.Note: A security best practice is to not use production secrets in test and development. Azure에 응용 프로그램을 게시 하는 경우에 Azure 웹 앱 포털에서 응용 프로그램 설정으로 SendGrid 암호를 설정할 수 있습니다.If you publish the app to Azure, you can set the SendGrid secrets as application settings in the Azure Web App portal. 구성 시스템에는 환경 변수에서 키를 읽을 설정 되었습니다.The configuration system is setup to read keys from environment variables.

등록 시 로그인을 방지Prevent login at registration

현재 템플릿과 함께 사용자 등록 양식을 완료 되는 로그인 (인증).With the current templates, once a user completes the registration form, they are logged in (authenticated). 일반적으로 자신의 전자 메일 기록 하기 전에 확인 하려고 합니다.You generally want to confirm their email before logging them in. 아래 섹션에 것을 요구 하도록 코드 수정 기록 하기 전에 새로운 사용자가 확인 된 전자 메일입니다.In the section below, we will modify the code to require new users have a confirmed email before they are logged in. 업데이트는 [HttpPost] Login 작업에는 AccountController.cs 다음 강조 표시 된 변경 내용과 파일을 합니다.Update the [HttpPost] Login action in the AccountController.cs file with the following highlighted changes.

//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
{
    ViewData["ReturnUrl"] = returnUrl;
    if (ModelState.IsValid)
    {
        // Require the user to have a confirmed email before they can log on.
        var user = await _userManager.FindByEmailAsync(model.Email);
        if (user != null)
        {
            if (!await _userManager.IsEmailConfirmedAsync(user))
            {
                ModelState.AddModelError(string.Empty, 
                              "You must have a confirmed email to log in.");
                return View(model);
            }
        }
        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account lockout, 
        // set lockoutOnFailure: true
        var result = await _signInManager.PasswordSignInAsync(model.Email,
            model.Password, model.RememberMe, lockoutOnFailure: false);
        if (result.Succeeded)
        {
            _logger.LogInformation(1, "User logged in.");
            return RedirectToLocal(returnUrl);
        }
        if (result.RequiresTwoFactor)
        {
            return RedirectToAction(nameof(SendCode),
                new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
        }
        if (result.IsLockedOut)
        {
            _logger.LogWarning(2, "User account locked out.");
            return View("Lockout");
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return View(model);
        }
    }

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

참고: 보안 모범 사례는 테스트 및 개발에서 생산 암호를 사용 하지 않도록 합니다.Note: A security best practice is to not use production secrets in test and development. Azure에 응용 프로그램을 게시 하는 경우에 Azure 웹 앱 포털에서 응용 프로그램 설정으로 SendGrid 암호를 설정할 수 있습니다.If you publish the app to Azure, you can set the SendGrid secrets as application settings in the Azure Web App portal. 구성 시스템에는 환경 변수에서 키를 읽을 설정 되었습니다.The configuration system is setup to read keys from environment variables.

공유 및 로컬 로그인 계정을 결합합니다Combine social and local login accounts

참고:이 부분 ASP.NET Core에만 적용 1.x 합니다.Note: This section applies only to ASP.NET Core 1.x. ASP.NET에 대 한 핵심 2.x, 참조 문제입니다.For ASP.NET Core 2.x, see this issue.

이 섹션을 완료 하려면 외부 인증 공급자를 먼저 활성화 해야 합니다.To complete this section, you must first enable an external authentication provider. 참조 Facebook, Google 및 다른 외부 공급자를 사용 하 여 사용 하도록 설정 하면 인증합니다.See Enabling authentication using Facebook, Google and other external providers.

사용자 전자 메일 링크를 클릭 하 여 로컬 및 소셜 계정을 결합할 수 있습니다.You can combine local and social accounts by clicking on your email link. 그러나 다음 순서로 "RickAndMSFT@gmail.com"; 로컬 로그인으로 처음 만들어질를 만들어 계정을 소셜 로그인으로 먼저, 다음 로컬 로그인을 추가 합니다.In the following sequence, "RickAndMSFT@gmail.com" is first created as a local login; however, you can create the account as a social login first, then add a local login.

웹 응용 프로그램: RickAndMSFT@gmail.com 인증 된 사용자

클릭는 관리 링크 합니다.Click on the Manage link. 이 계정에 연결 된 참고 0 외부 (소셜 로그인)Note the 0 external (social logins) associated with this account.

보기를 관리

다른 로그인 서비스에 대 한 링크를 클릭 하 고 응용 프로그램 요청을 수락 합니다.Click the link to another login service and accept the app requests. 아래 이미지 Facebook 외부 인증 공급자입니다.In the image below, Facebook is the external authentication provider:

Facebook을 나열 하 여 외부 로그인 보기를 관리 합니다.

두 개의 계정은 결합 되었습니다.The two accounts have been combined. 두 계정으로 로그온 할 수 있게 됩니다.You will be able to log on with either account. 경우에 대비 다운 되는 인증 서비스에서 소셜의 로그 또는 쓰지만 대개은 स ॅ स 소셜 계정으로 로컬 계정을 추가 하려면 사용자가 할 수 있습니다.You might want your users to add local accounts in case their social log in authentication service is down, or more likely they have lost access to their social account.