ASP.NET Identity 데이터베이스

ASP.NET Core Identity 기본 템플릿 Database Diagram
ASP.NET Core Identity 기본 템플릿 Database Diagram

ASP.NET Identity는 .NET 애플리케이션에서 사용자 인증과 권한 관리를 담당하는 시스템입니다.

이 시스템은 7개의 핵심 테이블로 구성되어 있으며, 각각은 특별한 역할을 수행합니다.

🏗️ 전체 구조 개요

plaintext
👤 사용자 (AspNetUsers)
    ↕️ 다대다 관계
👥 역할 (AspNetRoles)
    ↕️
📋 권한/정보 (Claims)
🔐 로그인 정보 (Logins, Tokens)

📋 1. AspNetUsers - 사용자 기본 정보

역할: 회원가입한 사용자들의 기본 정보를 저장하는 메인 테이블

주요 필드 설명

필드명 타입 설명 예시
Id GUID 사용자 고유 식별자 a1b2c3d4-e5f6-...
UserName string 로그인 ID john_doe
Email string 이메일 주소 [email protected]
PasswordHash string 암호화된 비밀번호 AQAAAAEAACcQ...
EmailConfirmed bool 이메일 인증 완료 여부 true
TwoFactorEnabled bool 2단계 인증 활성화 여부 false
LockoutEnd DateTime? 계정 잠금 해제 시간 2024-12-31 23:59:59
AccessFailedCount int 로그인 실패 횟수 3

🔒 보안 관련 필드들

SecurityStamp: 보안이 변경될 때마다 갱신되는 "도장"

  • 비밀번호 변경, 이메일 변경 시 자동 갱신
  • 이전 로그인 세션들을 무효화하는 역할

ConcurrencyStamp: 동시 수정 방지 "버전 번호"

  • 여러 사용자가 같은 계정을 동시에 수정하는 것을 방지

💡 실제 사용 예시

csharp
// 사용자 계정 잠금 확인
if (user.LockoutEnd.HasValue && user.LockoutEnd > DateTime.UtcNow)
{
    // 계정이 잠겨있음
    return "계정이 일시적으로 잠겨있습니다.";
}

// 로그인 실패 횟수 증가
user.AccessFailedCount++;
if (user.AccessFailedCount >= 5)
{
    user.LockoutEnd = DateTime.UtcNow.AddMinutes(30);
}

👥 2. AspNetRoles - 역할 정의

역할: 사용자들을 그룹으로 분류하는 역할(Role) 정보 저장

주요 필드

필드명 설명 예시
Id 역할 고유 식별자 role-admin-001
Name 역할 이름 Administrator
NormalizedName 검색용 정규화된 이름 ADMINISTRATOR

🎭 일반적인 역할 예시

csharp
// 기본 역할들
var roles = new[]
{
    new IdentityRole { Name = "SuperAdmin", NormalizedName = "SUPERADMIN" },
    new IdentityRole { Name = "Admin", NormalizedName = "ADMIN" },
    new IdentityRole { Name = "Manager", NormalizedName = "MANAGER" },
    new IdentityRole { Name = "Employee", NormalizedName = "EMPLOYEE" },
    new IdentityRole { Name = "Customer", NormalizedName = "CUSTOMER" }
};

🔗 3. AspNetUserRoles - 사용자-역할 연결

역할: 어떤 사용자가 어떤 역할을 가지는지 매핑하는 중간 테이블

구조

필드명 설명
UserId 사용자 ID (외래키)
RoleId 역할 ID (외래키)

📊 관계 예시

plaintext
사용자 "김철수" (UserId: user123)
├── Admin 역할 (RoleId: role-admin)
└── Manager 역할 (RoleId: role-manager)

사용자 "이영희" (UserId: user456)
└── Employee 역할 (RoleId: role-employee)

💻 실제 사용법

csharp
// 사용자에게 역할 할당
await userManager.AddToRoleAsync(user, "Admin");

// 사용자의 모든 역할 조회
var userRoles = await userManager.GetRolesAsync(user);
// 결과: ["Admin", "Manager"]

// 특정 역할 확인
bool isAdmin = await userManager.IsInRoleAsync(user, "Admin");

🎫 4. Claims 시스템 - 세부 권한 관리

클레임(Claim)이란? 사용자나 역할에 대한 "주장" 또는 "속성"을 나타내는 이름-값 쌍입니다.

🔍 클레임 vs 역할 비교

구분 역할 (Role) 클레임 (Claim)
특징 그룹 단위 분류 개별 속성/권한
예시 "관리자", "직원" "게시물삭제권한", "IT부서소속"
유연성 제한적 매우 유연

🏷️ AspNetRoleClaims - 역할별 클레임

역할: 특정 역할에 속한 모든 사용자가 공통으로 가지는 권한/속성

필드명 설명 예시
RoleId 역할 ID role-admin
ClaimType 클레임 유형 Permission
ClaimValue 클레임 값 CanManageUsers

실제 예시:

csharp
// "Admin" 역할에 클레임 추가
var claims = new[]
{
    new Claim("Permission", "CanManageUsers"),
    new Claim("Permission", "CanDeletePosts"),
    new Claim("Permission", "CanViewReports"),
    new Claim("Department", "Management")
};

foreach (var claim in claims)
{
    await roleManager.AddClaimAsync(adminRole, claim);
}

👤 AspNetUserClaims - 개인별 클레임

역할: 특정 사용자에게만 부여되는 개별적인 권한/속성

필드명 설명 예시
UserId 사용자 ID user123
ClaimType 클레임 유형 SpecialPermission
ClaimValue 클레임 값 CanAccessBetaFeatures

실제 예시:

csharp
// 특정 사용자에게만 베타 기능 접근 권한 부여
var betaClaim = new Claim("Feature", "BetaAccess");
await userManager.AddClaimAsync(user, betaClaim);

// VIP 고객 표시
var vipClaim = new Claim("CustomerLevel", "VIP");
await userManager.AddClaimAsync(user, vipClaim);

🌐 5. AspNetUserLogins - 외부 로그인 연동

역할: 구글, 페이스북 등 외부 서비스를 통한 로그인 정보 저장

구조

필드명 설명 예시
LoginProvider 로그인 제공자 Google
ProviderKey 제공자 내 사용자 ID google-user-12345
ProviderDisplayName 화면 표시명 구글 계정
UserId 연결된 로컬 사용자 ID user123

🔄 연동 과정 예시

csharp
1. 사용자가 "구글로 로그인" 클릭
2. 구글에서 인증 완료 후 사용자 정보 반환 (ProviderKey: google-12345)
3. AspNetUserLogins 테이블에서 해당 ProviderKey 검색
4. 기존 계정이 있으면 로그인, 없으면 새 계정 생성

💻 실제 구현

csharp
// 외부 로그인 정보 추가
var loginInfo = new UserLoginInfo("Google", "google-12345", "Google");
await userManager.AddLoginAsync(user, loginInfo);

// 사용자의 모든 외부 로그인 조회
var logins = await userManager.GetLoginsAsync(user);
// 결과: [{ Provider: "Google", Key: "google-12345" }, ...]

🎟️ 6. AspNetUserTokens - 인증 토큰 관리

역할: 사용자별 각종 보안 토큰 저장 (리프레시 토큰, 인증 코드 등)

구조

필드명 설명 예시
UserId 사용자 ID user123
LoginProvider 토큰 발급자 MyApp
Name 토큰 이름 RefreshToken
Value 토큰 실제 값 abc123def456...

🔐 토큰 유형별 예시

1. 리프레시 토큰

csharp
// 리프레시 토큰 저장
await userManager.SetAuthenticationTokenAsync(
    user, "MyApp", "RefreshToken", "abc123def456ghi789");

2. 이메일 인증 토큰

csharp
// 이메일 인증 토큰 생성 및 저장
var emailToken = await userManager.GenerateEmailConfirmationTokenAsync(user);
// 자동으로 AspNetUserTokens에 저장됨

3. 비밀번호 재설정 토큰

csharp
// 비밀번호 재설정 토큰 생성
var resetToken = await userManager.GeneratePasswordResetTokenAsync(user);

🎯 권한 검사 실제 활용법

1. 컨트롤러에서 역할 기반 권한 검사

csharp
[Authorize(Roles = "Admin,Manager")]
public class AdminController : Controller
{
    public IActionResult Dashboard()
    {
        return View();
    }
}

2. 클레임 기반 권한 검사

csharp
[Authorize(Policy = "CanManageUsers")]
public class UserManagementController : Controller
{
    public async Task<IActionResult> DeleteUser(string userId)
    {
        // 사용자 삭제 로직
        return Ok();
    }
}

// Startup.cs에서 정책 정의
services.AddAuthorization(options =>
{
    options.AddPolicy("CanManageUsers", policy =>
        policy.RequireClaim("Permission", "CanManageUsers"));
});

3. 코드에서 동적 권한 검사

csharp
public async Task<IActionResult> SomeAction()
{
    // 현재 사용자가 특정 클레임을 가지고 있는지 확인
    if (User.HasClaim("Permission", "CanDeletePosts"))
    {
        // 게시물 삭제 가능
    }
    
    // 역할 확인
    if (User.IsInRole("Admin"))
    {
        // 관리자 전용 기능
    }
    
    return View();
}

🏢 실무 시나리오 예시

회사 내부 시스템 권한 설계

1. 역할 구조

plaintext
SuperAdmin (최고 관리자)
├── Admin (일반 관리자)
├── HRManager (인사 관리자)
├── ProjectManager (프로젝트 관리자)
├── Developer (개발자)
├── Designer (디자이너)
└── Intern (인턴)

2. 클레임 설계

plaintext
// 부서별 클레임
ClaimType: "Department"
Values: "Engineering", "Design", "HR", "Marketing"

// 권한별 클레임
ClaimType: "Permission"
Values: "ViewSalary", "EditProject", "DeleteUser", "ViewReports"

// 레벨별 클레임
ClaimType: "Level"
Values: "Senior", "Junior", "Lead"

3. 실제 적용

csharp
// 사용자 "김개발"의 권한 설정
var developer = await userManager.FindByNameAsync("kim_developer");

// 역할 할당
await userManager.AddToRoleAsync(developer, "Developer");

// 개인 클레임 할당
await userManager.AddClaimAsync(developer, new Claim("Department", "Engineering"));
await userManager.AddClaimAsync(developer, new Claim("Level", "Senior"));
await userManager.AddClaimAsync(developer, new Claim("Permission", "ViewReports"));

4. 권한 검사

csharp
// 급여 정보는 HR 부서와 본인만 볼 수 있음
[Authorize]
public async Task<IActionResult> ViewSalary(string userId)
{
    var currentUser = await userManager.GetUserAsync(User);
    
    // 본인 정보이거나 HR 부서인 경우만 허용
    if (currentUser.Id == userId || 
        User.HasClaim("Department", "HR"))
    {
        return View();
    }
    
    return Forbid();
}

📊 테이블 간 관계 요약

csharp
AspNetUsers (사용자)
    ├── AspNetUserRoles → AspNetRoles (역할)
    ├── AspNetUserClaims (개인 클레임)
    ├── AspNetUserLogins (외부 로그인)
    └── AspNetUserTokens (인증 토큰)

AspNetRoles (역할)
    └── AspNetRoleClaims (역할별 클레임)

💡 핵심 포인트

  1. 역할(Role)은 사용자를 그룹으로 분류하는 개념
  2. 클레임(Claim)은 세부적인 권한과 속성을 정의하는 개념
  3. 역할 클레임은 해당 역할의 모든 사용자에게 적용
  4. 사용자 클레임은 특정 사용자에게만 적용
  5. 외부 로그인으로 여러 인증 방식 통합 가능
  6. 토큰으로 다양한 인증 시나리오 지원

이러한 구조를 통해 복잡한 권한 관리와 인증 시스템을 유연하고 안전하게 구현할 수 있습니다.