
ASP.NET Identity는 .NET 애플리케이션에서 사용자 인증과 권한 관리를 담당하는 시스템입니다.
이 시스템은 7개의 핵심 테이블로 구성되어 있으며, 각각은 특별한 역할을 수행합니다.
🏗️ 전체 구조 개요
👤 사용자 (AspNetUsers) ↕️ 다대다 관계 👥 역할 (AspNetRoles) ↕️ 📋 권한/정보 (Claims) 🔐 로그인 정보 (Logins, Tokens)
📋 1. AspNetUsers – 사용자 기본 정보
역할: 회원가입한 사용자들의 기본 정보를 저장하는 메인 테이블
주요 필드 설명
필드명 | 타입 | 설명 | 예시 |
---|---|---|---|
Id | GUID | 사용자 고유 식별자 | a1b2c3d4-e5f6-... |
UserName | string | 로그인 ID | john_doe |
Email | string | 이메일 주소 | john@example.com |
PasswordHash | string | 암호화된 비밀번호 | AQAAAAEAACcQ... |
EmailConfirmed | bool | 이메일 인증 완료 여부 | true |
TwoFactorEnabled | bool | 2단계 인증 활성화 여부 | false |
LockoutEnd | DateTime? | 계정 잠금 해제 시간 | 2024-12-31 23:59:59 |
AccessFailedCount | int | 로그인 실패 횟수 | 3 |
🔒 보안 관련 필드들
SecurityStamp: 보안이 변경될 때마다 갱신되는 “도장”
- 비밀번호 변경, 이메일 변경 시 자동 갱신
- 이전 로그인 세션들을 무효화하는 역할
ConcurrencyStamp: 동시 수정 방지 “버전 번호”
- 여러 사용자가 같은 계정을 동시에 수정하는 것을 방지
💡 실제 사용 예시
// 사용자 계정 잠금 확인 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 |
🎭 일반적인 역할 예시
// 기본 역할들 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 (외래키) |
📊 관계 예시
사용자 "김철수" (UserId: user123) ├── Admin 역할 (RoleId: role-admin) └── Manager 역할 (RoleId: role-manager) 사용자 "이영희" (UserId: user456) └── Employee 역할 (RoleId: role-employee)
💻 실제 사용법
// 사용자에게 역할 할당 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 |
실제 예시:
// "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 |
실제 예시:
// 특정 사용자에게만 베타 기능 접근 권한 부여 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 |
🔄 연동 과정 예시
1. 사용자가 "구글로 로그인" 클릭 2. 구글에서 인증 완료 후 사용자 정보 반환 (ProviderKey: google-12345) 3. AspNetUserLogins 테이블에서 해당 ProviderKey 검색 4. 기존 계정이 있으면 로그인, 없으면 새 계정 생성
💻 실제 구현
// 외부 로그인 정보 추가 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. 리프레시 토큰
// 리프레시 토큰 저장 await userManager.SetAuthenticationTokenAsync( user, "MyApp", "RefreshToken", "abc123def456ghi789");
2. 이메일 인증 토큰
// 이메일 인증 토큰 생성 및 저장 var emailToken = await userManager.GenerateEmailConfirmationTokenAsync(user); // 자동으로 AspNetUserTokens에 저장됨
3. 비밀번호 재설정 토큰
// 비밀번호 재설정 토큰 생성 var resetToken = await userManager.GeneratePasswordResetTokenAsync(user);
🎯 권한 검사 실제 활용법
1. 컨트롤러에서 역할 기반 권한 검사
[Authorize(Roles = "Admin,Manager")] public class AdminController : Controller { public IActionResult Dashboard() { return View(); } }
2. 클레임 기반 권한 검사
[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. 코드에서 동적 권한 검사
public async Task<IActionResult> SomeAction() { // 현재 사용자가 특정 클레임을 가지고 있는지 확인 if (User.HasClaim("Permission", "CanDeletePosts")) { // 게시물 삭제 가능 } // 역할 확인 if (User.IsInRole("Admin")) { // 관리자 전용 기능 } return View(); }
🏢 실무 시나리오 예시
회사 내부 시스템 권한 설계
1. 역할 구조
SuperAdmin (최고 관리자) ├── Admin (일반 관리자) ├── HRManager (인사 관리자) ├── ProjectManager (프로젝트 관리자) ├── Developer (개발자) ├── Designer (디자이너) └── Intern (인턴)
2. 클레임 설계
// 부서별 클레임 ClaimType: "Department" Values: "Engineering", "Design", "HR", "Marketing" // 권한별 클레임 ClaimType: "Permission" Values: "ViewSalary", "EditProject", "DeleteUser", "ViewReports" // 레벨별 클레임 ClaimType: "Level" Values: "Senior", "Junior", "Lead"
3. 실제 적용
// 사용자 "김개발"의 권한 설정 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. 권한 검사
// 급여 정보는 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(); }
📊 테이블 간 관계 요약
AspNetUsers (사용자) ├── AspNetUserRoles → AspNetRoles (역할) ├── AspNetUserClaims (개인 클레임) ├── AspNetUserLogins (외부 로그인) └── AspNetUserTokens (인증 토큰) AspNetRoles (역할) └── AspNetRoleClaims (역할별 클레임)
💡 핵심 포인트
- 역할(Role)은 사용자를 그룹으로 분류하는 개념
- 클레임(Claim)은 세부적인 권한과 속성을 정의하는 개념
- 역할 클레임은 해당 역할의 모든 사용자에게 적용
- 사용자 클레임은 특정 사용자에게만 적용
- 외부 로그인으로 여러 인증 방식 통합 가능
- 토큰으로 다양한 인증 시나리오 지원
이러한 구조를 통해 복잡한 권한 관리와 인증 시스템을 유연하고 안전하게 구현할 수 있습니다.