ASP.NET Core의 계정 확인 및 암호 복구

Rick Anderson, PonantJoe Audette

이 자습서에서는 전자 메일 확인 및 암호 재설정을 사용 하 여 ASP.NET Core 앱을 빌드하는 방법을 보여 줍니다. 이 자습서는 시작 항목이 아닙니다 . 다음 사항을 잘 알고 있어야 합니다.

필수 구성 요소

.NET Core 3.0 SDK 이상

인증을 사용 하 여 웹 앱 만들기 및 테스트

다음 명령을 실행 하 여 인증을 사용 하는 웹 앱을 만듭니다.

dotnet new webapp -au Individual -uld -o WebPWrecover
cd WebPWrecover
dotnet run

앱을 실행 하 고, 등록 링크를 선택 하 고, 사용자를 등록 합니다. 등록 되 면 /Identity/Account/RegisterConfirmation 전자 메일 확인을 시뮬레이트하는 링크를 포함 하는 to 페이지로 리디렉션됩니다.

  • 링크를 선택 Click here to confirm your account 합니다.
  • 로그인 링크를 선택 하 고 동일한 자격 증명을 사용 하 여 로그인 합니다.
  • Hello YourEmail@provider.com!페이지로 리디렉션되는 링크를 선택 합니다 /Identity/Account/Manage/PersonalData .
  • 왼쪽에서 개인 데이터 탭을 선택 하 고 삭제 를 선택 합니다.

전자 메일 공급자 구성

이 자습서에서는 SendGrid 를 사용 하 여 전자 메일을 보냅니다. 전자 메일을 보내려면 SendGrid 계정 및 키가 필요 합니다. 다른 전자 메일 공급자를 사용할 수 있습니다. SendGrid 또는 다른 전자 메일 서비스를 사용 하 여 전자 메일을 보내는 것이 좋습니다. SMTP는 안전 하 게 보호 하 고 올바르게 설정 하기 어렵습니다.

SendGrid 계정에는 발신자를 추가해야 할 수 있습니다.

보안 전자 메일 키를 인출 하는 클래스를 만듭니다. 이 샘플의 경우 Services/AuthMessageSenderOptions 을 만듭니다.

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

SendGrid 사용자 비밀 구성

SendGridKey 암호 관리자 도구를 사용 하 여를 설정 합니다. 예를 들면 다음과 같습니다.

dotnet user-secrets set SendGridKey <key>

Successfully saved SendGridKey to the secret store.

Windows에서 비밀 관리자는 디렉터리의 파일 에 있는secrets.js 의 키/값 쌍을 저장 %APPDATA%/Microsoft/UserSecrets/<WebAppName-userSecretsId> 합니다.

파일의 secrets.js 내용이 암호화 되지 않았습니다. 다음 태그는 파일 의secrets.js 을 보여 줍니다. SendGridKey값이 제거 되었습니다.

{
  "SendGridKey": "<key removed>"
}

자세한 내용은 옵션 패턴구성을 참조 하세요.

SendGrid 설치

이 자습서에서는 SendGrid를 통해 전자 메일 알림을 추가 하는 방법을 보여 주지만 SMTP 및 기타 메커니즘을 사용 하 여 전자 메일을 보낼 수 있습니다.

NuGet 패키지를 설치 합니다 SendGrid .

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

Install-Package SendGrid

무료 SendGrid 계정에 등록 하려면 SendGrid를 사용 하 여 시작 를 참조 하세요.

IEmailSender 구현

를 구현 하려면 IEmailSender 다음과 유사한 코드를 사용 하 여 서비스/emailsender .cs 를 만듭니다.

using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.Extensions.Options;
using SendGrid;
using SendGrid.Helpers.Mail;
using System.Threading.Tasks;

namespace WebPWrecover.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", "Password Recovery"),
                Subject = subject,
                PlainTextContent = message,
                HtmlContent = message
            };
            msg.AddTo(new EmailAddress(email));

            // Disable click tracking.
            // See https://sendgrid.com/docs/User_Guide/Settings/tracking.html
            msg.SetClickTracking(false, false);

            return client.SendEmailAsync(msg);
        }
    }
}

전자 메일을 지원 하도록 시작 구성

ConfigureServices 시작 .cs 파일의 메서드에 다음 코드를 추가 합니다.

  • EmailSender 임시 서비스로 추가 합니다.
  • AuthMessageSenderOptions구성 인스턴스를 등록 합니다.
public void ConfigureServices(IServiceCollection services)
{

    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDefaultIdentity<IdentityUser>(
                  options => options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>();

    // requires
    // using Microsoft.AspNetCore.Identity.UI.Services;
    // using WebPWrecover.Services;
    services.AddTransient<IEmailSender, EmailSender>();
    services.Configure<AuthMessageSenderOptions>(Configuration);

    services.AddRazorPages();
}

스 캐 폴드 RegisterConfirmation

스 캐 폴드 Identity 및 스 캐 폴드에 대 한 지침을 따릅니다 RegisterConfirmation .

기본 계정 확인 사용 안 함

기본 템플릿을 사용 하면 사용자가 Account.RegisterConfirmation 계정 확인을 위해 링크를 선택할 수 있는 위치로 리디렉션됩니다. 기본값은 Account.RegisterConfirmation 테스트에 사용 되며 자동 계정 확인은 프로덕션 앱에서 사용 하지 않도록 설정 해야 합니다.

확인 된 계정을 요구 하 고 등록 시 즉각적인 로그인을 방지 하려면 DisplayConfirmAccountLink = false /Areas/ Identity /Pages/Account/RegisterConfirmation.cshtml.cs 에서를 설정 합니다.

[AllowAnonymous]
public class RegisterConfirmationModel : PageModel
{
    private readonly UserManager<IdentityUser> _userManager;
    private readonly IEmailSender _sender;

    public RegisterConfirmationModel(UserManager<IdentityUser> userManager, IEmailSender sender)
    {
        _userManager = userManager;
        _sender = sender;
    }

    public string Email { get; set; }

    public bool DisplayConfirmAccountLink { get; set; }

    public string EmailConfirmationUrl { get; set; }

    public async Task<IActionResult> OnGetAsync(string email, string returnUrl = null)
    {
        if (email == null)
        {
            return RedirectToPage("/Index");
        }

        var user = await _userManager.FindByEmailAsync(email);
        if (user == null)
        {
            return NotFound($"Unable to load user with email '{email}'.");
        }

        Email = email;
        // Once you add a real email sender, you should remove this code that lets you confirm the account
        DisplayConfirmAccountLink = false;
        if (DisplayConfirmAccountLink)
        {
            var userId = await _userManager.GetUserIdAsync(user);
            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
            EmailConfirmationUrl = Url.Page(
                "/Account/ConfirmEmail",
                pageHandler: null,
                values: new { area = "Identity", userId = userId, code = code, returnUrl = returnUrl },
                protocol: Request.Scheme);
        }

        return Page();
    }
}

등록, 전자 메일 확인 및 암호 재설정

웹 앱을 실행 하 고 계정 확인 및 암호 복구 흐름을 테스트 합니다.

  • 앱을 실행 하 고 새 사용자를 등록 합니다.
  • 계정 확인 링크에 대 한 전자 메일을 확인 합니다. 전자 메일을 받을 수 없는 경우 디버그 전자 메일 을 참조 하세요.
  • 링크를 클릭 하 여 전자 메일을 확인 합니다.
  • 전자 메일 및 암호를 사용 하 여 로그인 합니다.
  • 로그아웃합니다.

암호 재설정 테스트

  • 로그인 하는 경우 로그 아웃 을 선택 합니다.
  • 로그인 링크를 선택 하 고 암호를 잊으셨나요? 링크를 선택 합니다.
  • 계정을 등록 하는 데 사용한 전자 메일을 입력 합니다.
  • 암호를 재설정 하는 링크가 포함 된 전자 메일이 전송 됩니다. 전자 메일을 확인 하 고 링크를 클릭 하 여 암호를 다시 설정 합니다. 암호를 성공적으로 재설정 한 후에는 전자 메일 및 새 암호로 로그인 할 수 있습니다.

전자 메일 다시 보내기 확인

ASP.NET Core 5.0 이상에서는 로그인 페이지에서 전자 메일 다시 보내기 확인 링크를 선택 합니다.

전자 메일 및 작업 시간 제한 변경

기본 비활성 시간 제한은 14 일입니다. 다음 코드는 비활성 시간 제한을 5 일로 설정 합니다.

services.ConfigureApplicationCookie(o => {
    o.ExpireTimeSpan = TimeSpan.FromDays(5);
    o.SlidingExpiration = true;
});

모든 데이터 보호 토큰 변경 lifespans

다음 코드는 모든 데이터 보호 토큰 제한 시간을 3 시간으로 변경 합니다.

public void ConfigureServices(IServiceCollection services)
{

    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDefaultIdentity<IdentityUser>(
                  options => options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>();

    services.Configure<DataProtectionTokenProviderOptions>(o =>
       o.TokenLifespan = TimeSpan.FromHours(3));

    services.AddTransient<IEmailSender, EmailSender>();
    services.Configure<AuthMessageSenderOptions>(Configuration);

    services.AddRazorPages();
}

기본 제공 Identity 사용자 토큰 ( AspNetCore/src/ Identity /Extensions.Core/src/TokenOptions.cs 참조)에는 1 일 시간 제한이있습니다.

전자 메일 토큰 수명 변경

Identity 사용자 토큰 의 기본 토큰 수명은 1 일입니다. 이 섹션에서는 전자 메일 토큰 수명을 변경 하는 방법을 보여 줍니다.

사용자 지정 DataProtectorTokenProvider <TUser> 및를 추가 합니다 DataProtectionTokenProviderOptions .

public class CustomEmailConfirmationTokenProvider<TUser>
                                       : DataProtectorTokenProvider<TUser> where TUser : class
{
    public CustomEmailConfirmationTokenProvider(IDataProtectionProvider dataProtectionProvider,
        IOptions<EmailConfirmationTokenProviderOptions> options,
        ILogger<DataProtectorTokenProvider<TUser>> logger)
                                          : base(dataProtectionProvider, options, logger)
    {

    }
}
public class EmailConfirmationTokenProviderOptions : DataProtectionTokenProviderOptions
{
    public EmailConfirmationTokenProviderOptions()
    {
        Name = "EmailDataProtectorTokenProvider";
        TokenLifespan = TimeSpan.FromHours(4);
    }
}

서비스 컨테이너에 사용자 지정 공급자를 추가 합니다.

public void ConfigureServices(IServiceCollection services)
{

    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDefaultIdentity<IdentityUser>(config =>
    {
        config.SignIn.RequireConfirmedEmail = true;
        config.Tokens.ProviderMap.Add("CustomEmailConfirmation",
            new TokenProviderDescriptor(
                typeof(CustomEmailConfirmationTokenProvider<IdentityUser>)));
        config.Tokens.EmailConfirmationTokenProvider = "CustomEmailConfirmation";
      }).AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddTransient<CustomEmailConfirmationTokenProvider<IdentityUser>>();

    services.AddTransient<IEmailSender, EmailSender>();
    services.Configure<AuthMessageSenderOptions>(Configuration);

    services.AddRazorPages();
}

디버그 전자 메일

전자 메일을 사용할 수 없는 경우:

  • EmailSender.Execute가 호출 되었는지 확인 하려면에서 중단점을 설정 SendGridClient.SendEmailAsync 합니다.
  • 비슷한 코드를 사용 하 여 전자 메일을 보내는 콘솔 앱 을 만듭니다 EmailSender.Execute .
  • 전자 메일 작업 페이지를 검토 합니다.
  • 스팸 폴더를 확인 합니다.
  • 다른 전자 메일 공급자 (Microsoft, Yahoo, Gmail 등)에서 다른 전자 메일 별칭을 사용해 보세요.
  • 다른 전자 메일 계정으로 전송 해 보세요.

보안 모범 사례 는 테스트 및 개발에서 프로덕션 암호를 사용 하지 않는 것입니다. Azure에 앱을 게시 하는 경우 Azure 웹 앱 포털에서 SendGrid 비밀을 응용 프로그램 설정으로 설정 합니다. 구성 시스템은 환경 변수에서 키를 읽도록 설정 되어 있습니다.

소셜 및 로컬 로그인 계정 결합

이 섹션을 완료 하려면 먼저 외부 인증 공급자를 사용 하도록 설정 해야 합니다. Facebook, Google 및 외부 공급자 인증을 참조 하세요.

전자 메일 링크를 클릭 하 여 로컬 및 소셜 계정을 결합할 수 있습니다. 다음 시퀀스에서는 " RickAndMSFT@gmail.com "이 (가) 로컬 로그인으로 먼저 생성 되지만 계정을 소셜 로그인으로 먼저 만든 다음 로컬 로그인을 추가할 수 있습니다.

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

관리 링크를 클릭 합니다. 이 계정과 연결 된 0 외부 (소셜 로그인)를 확인 합니다.

보기 관리

다른 로그인 서비스에 대한 링크를 클릭하고 앱 요청을 수락합니다. 다음 이미지에서 Facebook은 외부 인증 공급자입니다.

Facebook을 나열하는 외부 로그인 보기 관리

두 계정이 결합되었습니다. 두 계정 중 하나를 사용하여 로그인할 수 있습니다. 소셜 로그인 인증 서비스가 다운되거나 소셜 계정에 대한 액세스 권한이 손실된 경우 사용자가 로컬 계정을 추가하도록 할 수 있습니다.

사이트에 사용자가 있는 후 계정 확인 사용

사용자가 있는 사이트에서 계정 확인을 사용하도록 설정하면 모든 기존 사용자가 잠깁니다. 기존 사용자는 계정이 확인되지 않으므로 잠겨 있습니다. 기존 사용자 잠금을 해결하려면 다음 방법 중 하나를 사용합니다.

  • 모든 기존 사용자를 확인하는 것으로 표시하도록 데이터베이스를 업데이트합니다.
  • 기존 사용자를 확인합니다. 예를 들어 확인 링크가 있는 이메일을 일괄 처리로 보냅니다.

필수 구성 요소

.NET Core 2.2 SDK 이상

웹앱 및 스캐폴드 만들기 Identity

다음 명령을 실행하여 인증을 사용하여 웹앱을 만듭니다.

dotnet new webapp -au Individual -uld -o WebPWrecover
cd WebPWrecover
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet tool install -g dotnet-aspnet-codegenerator
dotnet aspnet-codegenerator identity -dc WebPWrecover.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.Logout;Account.ConfirmEmail"
dotnet ef database drop -f
dotnet ef database update
dotnet run

참고

에서 를 구성한 경우 PasswordOptions Startup.ConfigureServices 스캐폴드된 페이지의 속성에 [StringLength] 특성 구성이 필요할 수 Password Identity 있습니다. InputModel Password 속성은 Areas/Identity/Pages/Account/Register.cshtml.cs 를 스캐폴딩한 후 파일에 Identity 있습니다.

새 사용자 등록 테스트

앱을 실행하고 등록 링크를 선택한 다음 사용자를 등록합니다. 이 시점에서 전자 메일에 대한 유일한 유효성 검사는 특성을 가진 [EmailAddress] 것입니다. 등록을 제출하면 앱에 로그인됩니다. 자습서의 후반부에서 새 사용자가 이메일의 유효성을 검사할 때까지 로그인할 수 없도록 코드가 업데이트됩니다.

데이터베이스 보기 Identity

  • 보기 메뉴에서 SQL Server 개체 탐색기 (SSOX)를 선택 합니다.
  • (Localdb) MSSQLLocalDB (SQL Server 13) 로 이동 합니다. Dbo를 마우스 오른쪽 단추로 클릭 합니다. AspNetUsers > 뷰 데이터:

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

테이블의 EmailConfirmed 필드는 False 입니다.

앱이 확인 이메일을 보낼 때 다음 단계에서 이 메일을 다시 사용할 수 있습니다. 행을 마우스 오른쪽 단추로 클릭하고 삭제를 선택합니다. 이메일 별칭을 삭제하면 다음 단계에서 더 쉽게 할 수 있습니다.

이메일 확인 필요

새 사용자 등록의 전자 메일을 확인하는 것이 가장 좋습니다. 메일 확인은 다른 사람을 가장하지 않는지 확인하는 데 도움이 됩니다(즉, 다른 사람의 메일에 등록되지 않음). 토론 포럼이 있고 " "가 " "로 등록되지 않도록 방지하려고 yli@example.com nolivetto@contoso.com 했습니다. 이메일 확인 없이 " nolivetto@contoso.com "는 앱에서 원치 않는 이메일을 받을 수 있습니다. 사용자가 실수로 ylo@example.com ""로 등록했고 "yli"의 철자가 잘못되었다고 가정합니다. 앱에 올바른 이메일이 없으므로 암호 복구를 사용할 수 없습니다. 이메일 확인은 봇으로부터 제한된 보호를 제공합니다. 메일 확인은 많은 메일 계정을 가진 악의적인 사용자로부터 보호를 제공하지 않습니다.

일반적으로 새 사용자가 확인된 전자 메일을 받기 전에 웹 사이트에 데이터를 게시하지 못하도록 방지하려고 합니다.

Startup.ConfigureServices확인된 전자 메일을 요구하도록 를 업데이트합니다.

public void ConfigureServices(IServiceCollection services)
{

    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));

    services.AddDefaultIdentity<IdentityUser>(config =>
    {
        config.SignIn.RequireConfirmedEmail = true;
    })
        .AddDefaultUI(UIFramework.Bootstrap4)
        .AddEntityFrameworkStores<ApplicationDbContext>();

    // requires
    // using Microsoft.AspNetCore.Identity.UI.Services;
    // using WebPWrecover.Services;
    services.AddTransient<IEmailSender, EmailSender>();
    services.Configure<AuthMessageSenderOptions>(Configuration);

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

config.SignIn.RequireConfirmedEmail = true; 에서는 등록된 사용자가 자신의 전자 메일이 확인될 때까지 로그인할 수 없도록 합니다.

전자 메일 공급자 구성

이 자습서에서는 SendGrid를 사용하여 이메일을 보냅니다. 전자 메일을 보내려면 SendGrid 계정 및 키가 필요합니다. 다른 전자 메일 공급자를 사용할 수 있습니다. ASP.NET Core 2.x에는 System.Net.Mail 앱에서 메일을 보낼 수 있는 가 포함되어 있습니다. SendGrid 또는 다른 이메일 서비스를 사용하여 이메일을 보내는 것이 좋습니다. SMTP는 보안을 설정하고 올바르게 설정하기 어렵습니다.

보안 전자 메일 키를 가져오는 클래스를 만듭니다. 이 샘플의 경우 Services/AuthMessageSenderOptions.cs를 만듭니다.

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

SendGrid 사용자 비밀 구성

비밀 관리자 도구를 사용하여 SendGridUserSendGridKey 설정합니다. 예를 들면 다음과 같습니다.

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

Windows 비밀 관리자는 디렉터리에 있는 파일의 secrets.js 키/값 쌍을 %APPDATA%/Microsoft/UserSecrets/<WebAppName-userSecretsId> 저장합니다.

파일의 secrets.js 내용은 암호화되지 않습니다. 다음 태그는 파일의 secrets.js 보여줍니다. SendGridKey값이 제거되었습니다.

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

자세한 내용은 옵션 패턴구성을참조하세요.

SendGrid 설치

이 자습서에서는 SendGrid를통해 이메일 알림을 추가하는 방법을 보여 주지만 SMTP 및 기타 메커니즘을 사용하여 이메일을 보낼 수 있습니다.

NuGet 패키지를 설치합니다. SendGrid

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

Install-Package SendGrid

무료 SendGrid 계정에 등록하려면 시작 무료 SendGrid를 참조하세요.

IEmailSender 구현

를 구현하려면 다음과 유사한 코드를 사용하여 IEmailSender Services/EmailSender.cs를 만듭니다.

using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.Extensions.Options;
using SendGrid;
using SendGrid.Helpers.Mail;
using System.Threading.Tasks;

namespace WebPWrecover.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));

            // Disable click tracking.
            // See https://sendgrid.com/docs/User_Guide/Settings/tracking.html
            msg.SetClickTracking(false, false);

            return client.SendEmailAsync(msg);
        }
    }
}

이메일을 지원하도록 시작 구성

ConfigureServices Startup.cs 파일의 메서드에 다음 코드를 추가합니다.

  • EmailSender를 임시 서비스로 추가합니다.
  • 구성 AuthMessageSenderOptions 인스턴스를 등록합니다.
public void ConfigureServices(IServiceCollection services)
{

    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));

    services.AddDefaultIdentity<IdentityUser>(config =>
    {
        config.SignIn.RequireConfirmedEmail = true;
    })
        .AddDefaultUI(UIFramework.Bootstrap4)
        .AddEntityFrameworkStores<ApplicationDbContext>();

    // requires
    // using Microsoft.AspNetCore.Identity.UI.Services;
    // using WebPWrecover.Services;
    services.AddTransient<IEmailSender, EmailSender>();
    services.Configure<AuthMessageSenderOptions>(Configuration);

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

계정 확인 및 암호 복구 사용

템플릿에는 계정 확인 및 암호 복구를 위한 코드가 있습니다. OnPostAsync Areas/ Identity /Pages/Account/Register.cshtml.cs에서 메서드를 찾습니다.

다음 줄을 주석으로 하여 새로 등록된 사용자가 자동으로 로그인되지 않도록 방지합니다.

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

전체 메서드는 변경된 줄이 강조 표시된 채 표시됩니다.

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>.");

            //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();
}

이메일 등록, 확인 및 암호 재설정

웹앱을 실행하고 계정 확인 및 암호 복구 흐름을 테스트합니다.

  • 앱 실행 및 새 사용자 등록
  • 계정 확인 링크에 대한 메일을 확인합니다. 이메일을 받지 못하면 디버그 메일을 참조하세요.
  • 링크를 클릭하여 이메일을 확인합니다.
  • 이메일 및 암호로 로그인합니다.
  • 로그아웃합니다.

관리 페이지 보기

브라우저에서 사용자 이름 선택:  사용자 이름이 있는 브라우저 창

프로필 탭이 선택된 관리 페이지가 표시됩니다. 메일에는 이메일이 확인되었음을 나타내는 확인란이 표시됩니다.

암호 재설정 테스트

  • 로그인한 경우 로그아웃을 선택합니다.
  • 로그인 링크를 선택하고 암호를 잊으셨나요? 링크를 선택합니다.
  • 계정을 등록하는 데 사용한 이메일을 입력합니다.
  • 암호를 재설정하는 링크가 있는 전자 메일이 전송됩니다. 메일을 확인하고 링크를 클릭하여 암호를 재설정합니다. 암호가 성공적으로 재설정된 후 이메일 및 새 암호로 로그인할 수 있습니다.

이메일 및 활동 시간 제한 변경

기본 비활성 시간 제한은 14일입니다. 다음 코드는 비활성 시간 초과를 5일로 설정합니다.

services.ConfigureApplicationCookie(o => {
    o.ExpireTimeSpan = TimeSpan.FromDays(5);
    o.SlidingExpiration = true;
});

모든 데이터 보호 토큰 수명 변경

다음 코드는 모든 데이터 보호 토큰 제한 시간을 3시간으로 변경합니다.

public void ConfigureServices(IServiceCollection services)
{

    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));

    services.AddDefaultIdentity<IdentityUser>(config =>
    {
        config.SignIn.RequireConfirmedEmail = true;
    })
        .AddDefaultUI(UIFramework.Bootstrap4)
        .AddEntityFrameworkStores<ApplicationDbContext>();

    services.Configure<DataProtectionTokenProviderOptions>(o =>
                o.TokenLifespan = TimeSpan.FromHours(3));

    services.AddTransient<IEmailSender, EmailSender>();
    services.Configure<AuthMessageSenderOptions>(Configuration);

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

기본 제공 Identity 사용자 토큰(AspNetCore/src/ Identity /Extensions.Core/src/TokenOptions.cs 참조)에는 1일 시간 초과가있습니다.

이메일 토큰 수명 변경

Identity 사용자 토큰의 기본 토큰 수명은 1일입니다. 이 섹션에서는 이메일 토큰 수명을 변경하는 방법을 보여줍니다.

사용자 지정 DataProtectorTokenProvider <TUser> 및 를 추가합니다. DataProtectionTokenProviderOptions

public class CustomEmailConfirmationTokenProvider<TUser> 
                                       : DataProtectorTokenProvider<TUser> where TUser : class
{
    public CustomEmailConfirmationTokenProvider(IDataProtectionProvider dataProtectionProvider,
        IOptions<EmailConfirmationTokenProviderOptions> options) 
                                                        : base(dataProtectionProvider, options)
    {

    }
}
public class EmailConfirmationTokenProviderOptions : DataProtectionTokenProviderOptions
{
    public EmailConfirmationTokenProviderOptions()
    {
        Name = "EmailDataProtectorTokenProvider";
        TokenLifespan = TimeSpan.FromHours(4);
    }
}

서비스 컨테이너에 사용자 지정 공급자를 추가합니다.

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

    services.AddDefaultIdentity<IdentityUser>(config =>
    {
        config.SignIn.RequireConfirmedEmail = true;
        config.Tokens.ProviderMap.Add("CustomEmailConfirmation",
            new TokenProviderDescriptor(
                typeof(CustomEmailConfirmationTokenProvider<IdentityUser>)));
        config.Tokens.EmailConfirmationTokenProvider = "CustomEmailConfirmation";                
    })
        .AddDefaultUI(UIFramework.Bootstrap4)
        .AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddTransient<CustomEmailConfirmationTokenProvider<IdentityUser>>();
    services.AddTransient<IEmailSender, EmailSender>();            
    services.Configure<AuthMessageSenderOptions>(Configuration); // For SendGrid key.

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

이메일 다시 보내기 확인

GitHub 문제를 참조하세요.

이메일 디버그

전자 메일을 사용할 수 없는 경우:

  • 에서 중단점을 EmailSender.Execute 설정하여 SendGridClient.SendEmailAsync 가 호출되는지 확인합니다.
  • 유사한 코드를 사용하여 이메일을 보내는 콘솔 앱을 EmailSender.Execute 만듭니다.
  • 이메일 활동 페이지를 검토합니다.
  • 스팸 폴더를 확인합니다.
  • 다른 이메일 공급자(Microsoft, Yahoo, Gmail 등)에서 다른 이메일 별칭을 사용해 보세요.
  • 다른 이메일 계정으로 전송해 보세요.

보안 모범 사례는 테스트 및 개발에 프로덕션 비밀을 사용하지 않는 것입니다. Azure에 앱을 게시하는 경우 Azure 웹앱 포털에서 SendGrid 비밀을 애플리케이션 설정으로 설정할 수 있습니다. 구성 시스템은 환경 변수에서 키를 읽도록 설정됩니다.

소셜 및 로컬 로그인 계정 결합

이 섹션을 완료하려면 먼저 외부 인증 공급자를 사용하도록 설정해야 합니다. Facebook, Google 및 외부 공급자 인증을참조하세요.

이메일 링크를 클릭하여 로컬 및 소셜 계정을 결합할 수 있습니다. 다음 순서에서 " RickAndMSFT@gmail.com "은 먼저 로컬 로그인으로 생성됩니다. 그러나 먼저 소셜 로그인으로 계정을 만든 다음 로컬 로그인을 추가할 수 있습니다.

웹 애플리케이션: RickAndMSFT@gmail.com 사용자 인증

관리 링크를 클릭합니다. 이 계정과 연결된 외부(소셜 로그인) 0개에 유의합니다.

보기 관리

다른 로그인 서비스에 대한 링크를 클릭하고 앱 요청을 수락합니다. 다음 이미지에서 Facebook은 외부 인증 공급자입니다.

Facebook을 나열하는 외부 로그인 보기 관리

두 계정이 결합되었습니다. 두 계정 중 하나를 사용하여 로그인할 수 있습니다. 소셜 로그인 인증 서비스가 다운되거나 소셜 계정에 대한 액세스 권한이 손실된 경우 사용자가 로컬 계정을 추가하도록 할 수 있습니다.

사이트에 사용자가 있는 후 계정 확인 사용

사용자가 있는 사이트에서 계정 확인을 사용하도록 설정하면 모든 기존 사용자가 잠깁니다. 기존 사용자는 계정이 확인되지 않으므로 잠깁니다. 기존 사용자 잠금을 해결하려면 다음 방법 중 하나를 사용합니다.

  • 모든 기존 사용자를 확인하는 것으로 표시하도록 데이터베이스를 업데이트합니다.
  • 기존 사용자를 확인합니다. 예를 들어 확인 링크가 있는 이메일을 일괄 처리로 보냅니다.