상세 컨텐츠

본문 제목

[ASP.NET Core] Claim 인증과 권한

.NET/ASP.NET Core

by 클리엘 클리엘 2021. 11. 11. 01:22

본문

728x90

Claim은 특정한 key값을 통해 사용자 인증 및 권한을 관리하며 여기에 필요한 data를 추가하여 사용할 수 있는 인증방법입니다.

 

1. 기본설정

 

Startup.cs의 ConfigureServices() method에 인증 및 권한에 관련한 service를 추가합니다.

services.AddAuthentication(defaultScheme: CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(option => { option.AccessDeniedPath = "/Home/Error"; option.LoginPath = "/login"; });
services.AddAuthorization();

AddAuthentication()은 인증과 관련된 것으로 인증 관련 key값을 cookie에 생성하도록 하며 login을 통해 인증과정을 통과한 사용자라 하더라도 자신에게 권한이 없는 page로 접근 시 redirect되는 page를 option.AccessDeniedPath속성으로 지정하였습니다. 또한 아예 인증과정을 거치지 않은 익명사용자의 경우에도 인증이 필요한 page로의 접근시 option.LoginPath속성을 통해 login이 가능한 page를 바로 보여줄 수 있도록 하였습니다.

 

service를 추가하고 나면 Configure() method에도 필요한 설정을 추가해 줍니다.

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
});

2. login / logout 구현

 

우선 아래와 같이 간단한 login page를 만들고

<form method="post" asp-controller="Login" asp-action="Login" onsubmit="btnLogin.disabled = false; return true;">
    <input type="text" asp-for="UserID" placeholder="아이디" autofocus />
    <br />
    <input type="password" asp-for="UserPW" placeholder="비밀번호" />
    <br />
    <button type="submit" name="btnLogin">로그인</button>
</form>

login page에서 사용자 id와 비밀번호를 넘겨받아 인증을 처리하도록 합니다.

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;

namespace myWeb.Controllers
{
    public class LoginController : Controller
    {
        private HttpContext _context;

        public LoginController(IHttpContextAccessor accessor)
        {
            _context = accessor.HttpContext;
        }

        public IActionResult Index()
        {
            return View();
        }

        [HttpPost]
        [AutoValidateAntiforgeryToken]
        public async Task<IActionResult> Login(string userID, string userPW)
        {
            if (userID == "abcdef" && userPW == "1234")
            {
                var identity = new ClaimsIdentity(claims: new[] {
                    new Claim(type: ClaimTypes.Name, value: UserID),
                    new Claim(type: ClaimTypes.Role, value: "admin"),
                    new Claim(type: ClaimTypes.UserData, value: "관리자")
                }, authenticationType: CookieAuthenticationDefaults.AuthenticationScheme);

                await _context.SignInAsync(scheme: CookieAuthenticationDefaults.AuthenticationScheme, principal: new ClaimsPrincipal(identity: identity), properties: new AuthenticationProperties() { AllowRefresh = true, IsPersistent = true, ExpiresUtc = DateTime.UtcNow.AddMinutes(1) });

                TempData["result"] = "로그인에 성공하였습니다.";
            }
            else
            {
                TempData["result"] = "로그인에 실패하였습니다.";
            }

            return View("Index");
        }

        public async Task<IActionResult> Logout()
        {
            await _context.SignOutAsync(scheme: CookieAuthenticationDefaults.AuthenticationScheme);

            return RedirectToAction("Index", "Home");
        }
    }
}

Login() method에서는 id가 abcdef이고 비밀번호가 1234인 경우 인증을 통과하도록 되어 있으며 Claim을 통해 Name으로 사용자 ID를, Role을 통해서는 admin권한을 부여하고 있습니다. 예제에서는 admin명칭의 권한을 사용했지만 권한의 이름은 임의로 지정할 수 있습니다. 또한 UserData를 통해 임의의 추가적인 data도 설정하였는데 이는 필요하지 않으면 생략이 가능합니다.

 

AuthenticationProperties()에서는 몇 가지 추가적인 설정을 포함하고 있는데 그중 ExpiresUtc 속성은 Cookie인증의 만료시간을 지정하는 것입니다. 예제에서는 만료시간을 1분으로 하였는데, 말 그대로 1분이 지나면 인증 key가 만료되므로 사용자는 다시 login 하는 과정을 통해 재인증을 받아야 합니다. 다만 AllowRefresh 속성이 true이므로 1분 안에 사용자가  어떤 식으로든 server로의 요청을 발생시킨다면 1분이라는 시간은 요청이 발생할 때마다 자동 갱신됩니다.

 

3. 권한 설정

 

권한 처리가 필요한 경우 아래와 같이 Controller Class나 Action method에 Authorize Attribute를 설정할 수 있습니다.

//admin, superuser
[Authorize(Roles = "admin")]
public IActionResult Privacy()
{
    return View();
}

예제에서는 Privacy()로 접근하는데 admin권한을 요구하고 있으며 추가적인 권한이 필요하다면 주석에서 처럼 , 로 다수의 권한을 지정할 수 있습니다.

 

처음 Startup.cs에서 ConfigureServices() method에 option.AccessDeniedPath으로 Redirect 되는 경로를 지정했었는데 만약 Privacy()에 admin이 아닌 다른 권한을 가진 사용자가 접근하게 되면 AccessDeniedPath로 지정된 page가 대신 표시될 것입니다.

 

참고로 Authorize Attribute가 설정되어 있지 않다면 기본적으로 인증과 관련 없이 접근이 가능하게 되지만 이를 명시적으로 지정하려면 [AllowAnonymous] Attribute를 설정할 수 있습니다.

 

4. 인증정보 확인

 

Claim을 통해 설정한 사용자 정보는 아래와 같은 방법으로 가져올 수 있습니다.

@using System.Security.Claims

@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

@if (Context.User.Claims.Any())
{
    <h1>@User.Identity.Name</h1>
    <h1>@User.FindFirst(claim => claim.Type.Equals(ClaimTypes.Name)).Value</h1>
    <h1>@User.FindFirst(claim => claim.Type.Equals(ClaimTypes.UserData)).Value</h1>
}

 

728x90

관련글 더보기

댓글 영역