첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
본 블로그는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 블로그 콘텐츠 향상을 위해 쓰여집니다.

728x90
반응형
728x170

TestProject.zip
다운로드

▶ Data/DatabaseContext.cs

using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

namespace TestProject.Data
{
    /// <summary>
    /// 데이터베이스 컨텍스트
    /// </summary>
    public class DatabaseContext : IdentityDbContext
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - DatabaseContext(options)

        /// <summary>
        /// 생성자
        /// </summary>
        /// <param name="options">옵션</param>
        public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options)
        {
        }

        #endregion
    }
}

 

728x90

 

▶ appsettings.json

{
    "MailAddress" :
    {
        "Server"      : "smtp.live.com",
        "Port"        : 587,
        "SenderName"  : "sender",
        "SenderEmail" : "sender@hotmail.com",
        "Account"     : "sender@hotmail.com",
        "Password"    : "password",
        "Security"    : true
    },
    "Logging" :
    {
        "LogLevel" :
        {
            "Default"                    : "Information",
            "Microsoft"                  : "Warning",
            "Microsoft.Hosting.Lifetime" : "Information"
        }
    },
    "AllowedHosts" : "*"
}

 

300x250

 

▶ Startup.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NETCore.MailKit.Extensions;
using NETCore.MailKit.Infrastructure.Internal;

using TestProject.Data;

namespace TestProject
{
    /// <summary>
    /// 시작
    /// </summary>
    public class Startup
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 구성
        /// </summary>
        private IConfiguration configuration;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - Startup(configuration)

        /// <summary>
        /// 생성자
        /// </summary>
        /// <param name="configuration">구성</param>
        public Startup(IConfiguration configuration)
        {
            this.configuration = configuration;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 서비스 컬렉션 구성하기 - ConfigureServices(services)

        /// <summary>
        /// 서비스 컬렉션 구성하기
        /// </summary>
        /// <param name="services">서비스 컬렉션</param>
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<DatabaseContext>(options => { options.UseInMemoryDatabase("MemoryDB"); });

            services.AddIdentity<IdentityUser, IdentityRole>
            (
                options =>
                {
                    options.Password.RequiredLength         = 4;
                    options.Password.RequireDigit           = false;
                    options.Password.RequireNonAlphanumeric = false;
                    options.Password.RequireUppercase       = false;
                    options.SignIn.RequireConfirmedEmail    = true;
                }
            )
            .AddEntityFrameworkStores<DatabaseContext>()
            .AddDefaultTokenProviders();

            services.ConfigureApplicationCookie
            (
                options =>
                {
                    options.Cookie.Name = "Identity.Cookie";
                    options.LoginPath   = "/Home/Login";
                }
            );

            services.AddMailKit
            (
                options =>
                {
                    options.UseMailKit(this.configuration.GetSection("MailAddress").Get<MailKitOptions>());
                }
            );

            services.AddControllersWithViews();
        }

        #endregion
        #region 구성하기 - Configure(app, environment)

        /// <summary>
        /// 구성하기
        /// </summary>
        /// <param name="app">애플리케이션 빌더</param>
        /// <param name="environment">웹 호스트 환경</param>
        public void Configure(IApplicationBuilder app, IWebHostEnvironment environment)
        {
            if(environment.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseAuthentication();

            app.UseAuthorization();

            app.UseEndpoints
            (
                endpoints =>
                {
                    endpoints.MapDefaultControllerRoute();
                }
            );
        }

        #endregion
    }
}

 

▶ Controllers/HomeController.cs

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using NETCore.MailKit.Core;
using System.Threading.Tasks;

namespace TestProject.Controllers
{
    /// <summary>
    /// 홈 컨트롤러
    /// </summary>
    public class HomeController : Controller
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 사용자 관리자
        /// </summary>
        private readonly UserManager<IdentityUser> userManager;

        /// <summary>
        /// 서명 관리자
        /// </summary>
        private readonly SignInManager<IdentityUser> signInManager;

        /// <summary>
        /// E 메일 서비스
        /// </summary>
        private readonly IEmailService emailService;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - HomeController(userManager, signInManager, emailService)

        /// <summary>
        /// 생성자
        /// </summary>
        /// <param name="userManager">사용자 관리자</param>
        /// <param name="signInManager">서명 관리자</param>
        /// <param name="emailService">E 메일 서비스</param>
        public HomeController(UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager, IEmailService emailService)
        {
            this.userManager   = userManager;
            this.signInManager = signInManager;
            this.emailService  = emailService;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 인덱스 페이지 처리하기 - Index()

        /// <summary>
        /// 인덱스 페이지 처리하기
        /// </summary>
        /// <returns>액션 결과</returns>
        public IActionResult Index()
        {
            return View();
        }

        #endregion
        #region 비밀 페이지 처리하기 - Secret()

        /// <summary>
        /// 비밀 페이지 처리하기
        /// </summary>
        /// <returns>액션 결과</returns>
        [Authorize]
        public IActionResult Secret()
        {
            return View();
        }

        #endregion
        #region 로그인 페이지 처리하기 - Login()

        /// <summary>
        /// 로그인 페이지 처리하기
        /// </summary>
        /// <returns>액션 결과</returns>
        public IActionResult Login()
        {
            return View();
        }

        #endregion
        #region 로그인 페이지 처리하기 - Login(userName, password)

        /// <summary>
        /// 로그인 페이지 처리하기
        /// </summary>
        /// <param name="userName">사용자명</param>
        /// <param name="password">패스워드</param>
        /// <returns>액션 결과 태스크</returns>
        [HttpPost]
        public async Task<IActionResult> Login(string userName, string password)
        {
            IdentityUser identityUser = await this.userManager.FindByNameAsync(userName);

            if(identityUser != null)
            {
                Microsoft.AspNetCore.Identity.SignInResult signInResult = await this.signInManager.PasswordSignInAsync
                (
                    identityUser,
                    password,
                    false,
                    false
                );

                if(signInResult.Succeeded)
                {
                    return RedirectToAction("Index");
                }
            }

            return RedirectToAction("Index");
        }

        #endregion
        #region 등록 페이지 처리하기 - Register()

        /// <summary>
        /// 등록 페이지 처리하기
        /// </summary>
        /// <returns>액션 결과</returns>
        public IActionResult Register()
        {
            return View();
        }

        #endregion
        #region 등록 페이지 처리하기 - Register(userName, password, mailAddress)

        /// <summary>
        /// 등록 페이지 처리하기
        /// </summary>
        /// <param name="userName">사용자명</param>
        /// <param name="password">패스워드</param>
        /// <param name="mailAddress">메일 주소</param>
        /// <returns>액션 결과 태스크</returns>
        [HttpPost]
        public async Task<IActionResult> Register(string userName, string password, string mailAddress)
        {
            IdentityUser identityUser = new IdentityUser
            {
                UserName = userName,
                Email    = mailAddress
            };

            IdentityResult result = await this.userManager.CreateAsync(identityUser, password);

            if(result.Succeeded)
            {
                string code = await this.userManager.GenerateEmailConfirmationTokenAsync(identityUser);

                var link = Url.Action
                (
                    "ConfirmMailAddress",
                    "Home",
                    new { userID = identityUser.Id, code },
                    Request.Scheme,
                    Request.Host.ToString()
                );

                await this.emailService.SendAsync
                (
                    mailAddress,
                    "메일 주소 확인 요청",
                    $"<a href=\"{link}\">메일 주소 확인</a>",
                    true
                );

                return RedirectToAction("SendMailNotification");
            }

            return RedirectToAction("Index");
        }

        #endregion
        #region 메일 발송 통지 페이지 처리하기 - SendMailNotification()

        /// <summary>
        /// 메일 발송 통지 페이지 처리하기
        /// </summary>
        /// <returns>액션 결과</returns>
        public IActionResult SendMailNotification()
        {
            return View();
        }

        #endregion
        #region 메일 주소 확인 페이지 처리하기 - ConfirmMailAddress(userID, code)

        /// <summary>
        /// 메일 주소 확인 페이지 처리하기
        /// </summary>
        /// <param name="userID">사용자 ID</param>
        /// <param name="code">코드</param>
        /// <returns>액션 결과 태스크</returns>
        public async Task<IActionResult> ConfirmMailAddress(string userID, string code)
        {
            IdentityUser identityUser = await this.userManager.FindByIdAsync(userID);

            if(identityUser == null)
            {
                return BadRequest();
            }

            IdentityResult identityResult = await this.userManager.ConfirmEmailAsync(identityUser, code);

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

            return BadRequest();
        }

        #endregion
        #region 로그아웃 페이지 처리하기 - LogOut()

        /// <summary>
        /// 로그아웃 페이지 처리하기
        /// </summary>
        /// <returns>액션 결과 태스크</returns>
        public async Task<IActionResult> LogOut()
        {
            await this.signInManager.SignOutAsync();

            return RedirectToAction("Index");
        }

        #endregion
    }
}

 

▶ Views/Home/Index.cshtml

<h1>홈 페이지</h1>

 

▶ Views/Home/Register.cshtml

<h1>등록 페이지</h1>
<hr />
<form action="/Home/Register" method="post">
    사용자명 : <input type="text" name="username" value="" /><br />
    패스워드 : <input type="text" name="password" value="" /><br />
    메일주소 : <input type="text" name="mailAddress" value="" /><br />
    <button type="submit">등록</button>
</form>

 

▶ Views/Home/SendMailNotification.cshtml

<h2>메일을 발송했습니다.</h2>
<h3>메일을 확인해 주시기 바랍니다.</h3>

 

▶ Views/Home/ConfirmMailAddress.cshtml

<h2>메일을 확인해 주셔서 감사합니다. 아래에서 로그인을 해주시기 바랍니다.</h2>
<a href="/Home/Login">로그인 페이지 이동</a>

 

▶ Views/Home/Login.cshtml

<h1>로그인 페이지</h1>
<hr />
<form action="/Home/Login" method="post">
    사용자명 : <input type="text" name="userName" value="" /><br />
    패스워드 : <input type="text" name="password" value="" /><br />
    <button type="submit">로그인</button>
</form>

 

▶ Views/Home/Secret.cshtml

<h1>비밀 페이지</h1>

 

※ 테스트 방법

 

1. appsettings.json 파일의 MailAddress 섹션에서 SenderName, SendrEmail, Account, Password 항목을 적절히 설정한다.

2. 프로그램을 실행한다.

3. 웹 브라우저에서 https://localhost:44341/home/register 페이지로 이동하고 사용자를 등록한다.

※ [사용자명]과 [패스워드]에 테스트를 용이하기 위해서 각각 "test", "password"를 입력하고 [메일주소]는 받고자 하는 메일 주소를 입력한다.

4. 사용자 등록을 완료하면 입력한 메일을 수신하고 [메일 주소 확인] 링크를 클릭한다.

5. 웹 브라우저에서 https://localhost:44341/home/secret 페이지로 이동하면 로그인 페이지가 표시된다.

6. 로그인 페이지에서 상기 입력한 [사용자명]과 [패스워드]를 입력해 로그인한다.

728x90
반응형
그리드형
Posted by 사용자 icodebroker

댓글을 달아 주세요