LoginLibrary 1.2.0
dotnet add package LoginLibrary --version 1.2.0
NuGet\Install-Package LoginLibrary -Version 1.2.0
<PackageReference Include="LoginLibrary" Version="1.2.0" />
<PackageVersion Include="LoginLibrary" Version="1.2.0" />
<PackageReference Include="LoginLibrary" />
paket add LoginLibrary --version 1.2.0
#r "nuget: LoginLibrary, 1.2.0"
#:package LoginLibrary@1.2.0
#addin nuget:?package=LoginLibrary&version=1.2.0
#tool nuget:?package=LoginLibrary&version=1.2.0
LoginLibrary
웹 애플리케이션을 위한 백엔드 인증 서비스를 제공하는 C# 클래스 라이브러리입니다.
상태: ✅ 프로덕션 준비 완료 | 최종 버전: 1.2.0
개요
목표: 로그인, 세션 관리 및 사용자 CRUD 작업을 제공하는 재사용 가능한 라이브러리 프레임워크: .NET Framework 4.7.2 배포: NuGet 패키지
아키텍처
계층 구조
- Service Class: 진입점, 트랜잭션 관리
- Controller Class: 요청 처리/흐름 제어
- Logic Class: 핵심 비즈니스 로직 및 데이터 처리
데이터 액세스
- ORM: Entity Framework 6.x
- 세션: Redis (StackExchange.Redis) 또는 DB, 설정을 통해 구성 가능
- User Entity:
IUserBase인터페이스를 구현하는 제네릭 타입<T>사용
주요 기능
- 사용자 로그인/로그아웃
- 인증 방식 선택: JWT 토큰 또는 세션 기반 (환경 변수로 설정)
- 세션 저장소 선택: Memory, Database, Redis (환경 변수로 설정)
- OAuth 2.0 인증: Google, GitHub, Microsoft, Facebook 지원
- 🆕 Rate Limiting: 로그인 시도 제한 및 계정 잠금 기능
- 🆕 DI 지원: ASP.NET Core 의존성 주입 확장 메서드
- 사용자 CRUD 작업
- 비밀번호 해싱 (MD5 + Salt)
- 동적 요청 바인딩
- 이벤트 기반 알림 시스템
프로젝트 구조
LoginClassLib/
├── LoginLibrary/ # 핵심 라이브러리
│ ├── Models/ # 데이터 모델
│ │ ├── IUserBase.cs # 사용자 인터페이스
│ │ ├── UserSession.cs # 세션 엔티티
│ │ ├── LoginRequest.cs # 동적 요청 바인딩
│ │ ├── LoginAttempt.cs # 🆕 로그인 시도 기록 엔티티
│ │ ├── LoginResult.cs # 🆕 로그인 결과 모델
│ │ └── RateLimitSettings.cs # 🆕 Rate Limiting 설정
│ ├── Data/
│ │ └── LoginDbContext.cs # Entity Framework DbContext
│ ├── Services/ # 비즈니스 로직
│ │ ├── LoginService.cs # 핵심 인증 서비스
│ │ ├── ISessionManager.cs # 세션 관리 인터페이스
│ │ ├── MemorySessionManager.cs # 메모리 기반 세션 (개발/테스트용)
│ │ ├── DbSessionManager.cs # DB 기반 세션
│ │ ├── RedisSessionManager.cs # Redis 기반 세션
│ │ ├── IRateLimitService.cs # 🆕 Rate Limiting 인터페이스
│ │ ├── RateLimitService.cs # 🆕 Rate Limiting 구현
│ │ ├── Jwt/ # JWT 인증 모듈
│ │ │ ├── IJwtTokenManager.cs # JWT 토큰 관리 인터페이스
│ │ │ ├── JwtTokenManager.cs # JWT 토큰 생성/검증
│ │ │ └── JwtSessionAdapter.cs# JWT-세션 어댑터
│ │ └── OAuth/ # OAuth 2.0 인증 모듈
│ │ ├── IOAuthProvider.cs # OAuth 프로바이더 인터페이스
│ │ ├── OAuthProviderBase.cs# OAuth 프로바이더 기본 클래스
│ │ ├── OAuthService.cs # OAuth 서비스
│ │ ├── OAuthServiceFactory.cs # OAuth 서비스 팩토리
│ │ ├── OAuthTokenResponse.cs # OAuth 토큰 응답 모델
│ │ ├── GoogleOAuthProvider.cs # Google OAuth
│ │ ├── GitHubOAuthProvider.cs # GitHub OAuth
│ │ ├── MicrosoftOAuthProvider.cs # Microsoft OAuth
│ │ └── FacebookOAuthProvider.cs # Facebook OAuth
│ ├── Extensions/ # 🆕 확장 메서드
│ │ └── ServiceCollectionExtensions.cs # ASP.NET Core DI 확장
│ └── Utils/
│ ├── ConfigHelper.cs # 설정 관리
│ └── PasswordHasher.cs # 비밀번호 해싱
│
├── LoginLibrary.TestApp/ # 콘솔 테스트 애플리케이션
│ ├── Program.cs # CLI 메뉴
│ ├── User.cs # 테스트 사용자 모델
│ └── appsettings.json # 테스트 설정
│
├── LoginLibrary.WebApi/ # ASP.NET Core Web API
│ ├── Controllers/
│ │ └── AuthController.cs # 인증 API 엔드포인트
│ ├── Models/
│ │ └── ApiUser.cs # API 사용자 모델
│ ├── Program.cs # Web API 진입점
│ └── appsettings.json # Web API 설정 (Swagger 포함)
│
└── LoginLibrary.Tests/ # 단위 테스트
├── LoginServiceTests.cs # LoginService 테스트
├── PasswordHasherTests.cs # PasswordHasher 테스트
├── JwtTokenManagerTests.cs # JWT 토큰 관리자 테스트
└── JwtSessionAdapterTests.cs # JWT 세션 어댑터 테스트
설정
LoginLibrary는 다양한 환경과 설정 소스를 지원합니다.
환경 감지
라이브러리는 다음 환경 변수를 통해 현재 환경을 자동 감지합니다:
ASPNETCORE_ENVIRONMENT(ASP.NET Core)DOTNET_ENVIRONMENT(.NET 애플리케이션)ENVIRONMENT(일반)- 기본값:
Production
인증 방식 선택 (JWT vs Session)
환경 변수 또는 설정 파일로 인증 방식을 선택할 수 있습니다:
| 설정 키 | 값 | 설명 |
|---|---|---|
LoginLibrary:AuthMode |
Session (기본값) |
세션 기반 인증 |
LoginLibrary:AuthMode |
Jwt |
JWT 토큰 기반 인증 |
세션 저장소 선택 (Session 모드일 때)
세션 기반 인증 시 저장소를 선택할 수 있습니다:
| 설정 키 | 값 | 설명 |
|---|---|---|
LoginLibrary:SessionStorage |
Memory (기본값) |
메모리 저장 (개발/테스트용, 서버 재시작 시 소멸) |
LoginLibrary:SessionStorage |
Database |
데이터베이스 저장 (영구적) |
LoginLibrary:SessionStorage |
Redis |
Redis 저장 (고성능, 분산 환경에 적합) |
💡 권장 사항:
- 개발/테스트:
Memory- 빠른 시작, 외부 의존성 없음- 단일 서버 프로덕션:
Database- 영구 저장, 서버 재시작 후에도 세션 유지- 분산/고성능 환경:
Redis- 빠른 성능, 다중 서버 환경 지원
환경별 설정 파일
.env 파일
기본 .env:
LoginLibrary__AuthMode=Session
LoginLibrary__SessionStorage=Memory
LoginLibrary__PasswordSalt=DefaultSalt
개발 환경 (.env.development):
LoginLibrary__AuthMode=Session
LoginLibrary__SessionStorage=Memory
LoginLibrary__PasswordSalt=DevSalt123
프로덕션 환경 (.env.production):
LoginLibrary__AuthMode=Session
LoginLibrary__SessionStorage=Redis
LoginLibrary__RedisConnectionString=redis.production.com:6379,password=secret
LoginLibrary__PasswordSalt=ProductionSecureSalt
JWT 사용 시 (.env.jwt):
LoginLibrary__AuthMode=Jwt
LoginLibrary__Jwt__SecretKey=YourProductionSecretKey
LoginLibrary__Jwt__Issuer=YourAppName
LoginLibrary__Jwt__ExpirationMinutes=30
appsettings.json
{
"LoginLibrary": {
"AuthMode": "Session",
"SessionStorage": "Database",
"RedisConnectionString": "localhost:6379",
"PasswordSalt": "YourSecretSalt123",
"Jwt": {
"SecretKey": "YourSuperSecretKeyForJwtToken12345678901234567890",
"Issuer": "YourAppName",
"Audience": "YourAppClients",
"ExpirationMinutes": 30
}
}
}
App.config 예시
<configuration>
<appSettings>
<add key="LoginLibrary:AuthMode" value="Session" />
<add key="LoginLibrary:SessionStorage" value="Database" />
<add key="LoginLibrary:RedisConnectionString" value="localhost:6379" />
<add key="LoginLibrary:PasswordSalt" value="YourSecretSalt123" />
<add key="LoginLibrary:Jwt:SecretKey" value="YourSuperSecretKeyForJwtToken12345678901234567890" />
<add key="LoginLibrary:Jwt:Issuer" value="YourAppName" />
<add key="LoginLibrary:Jwt:Audience" value="YourAppClients" />
<add key="LoginLibrary:Jwt:ExpirationMinutes" value="30" />
</appSettings>
<connectionStrings>
<add name="LoginDbContext" value="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=LoginLibraryDb;Integrated Security=True" />
</connectionStrings>
</configuration>
환경 변수 설정
PowerShell:
# 환경 설정
$env:ENVIRONMENT="Development"
# 인증 방식 설정
$env:LoginLibrary__AuthMode="Jwt"
# JWT 설정
$env:LoginLibrary__Jwt__SecretKey="YourSuperSecretKeyForJwtToken12345678901234567890"
$env:LoginLibrary__Jwt__Issuer="YourAppName"
$env:LoginLibrary__Jwt__Audience="YourAppClients"
$env:LoginLibrary__Jwt__ExpirationMinutes="30"
Bash:
# 환경 설정
export ENVIRONMENT=Development
# 인증 방식 설정
export LoginLibrary__AuthMode=Jwt
# JWT 설정
export LoginLibrary__Jwt__SecretKey=YourSuperSecretKeyForJwtToken12345678901234567890
export LoginLibrary__Jwt__Issuer=YourAppName
export LoginLibrary__Jwt__Audience=YourAppClients
export LoginLibrary__Jwt__ExpirationMinutes=30
설정 우선 순위 (높음 → 낮음)
- 환경별 .env 파일 (
.env.production,.env.development등) - .env.local (개인 로컬 설정)
- .env (기본 환경 파일)
- appsettings.{Environment}.json (환경별 JSON)
- appsettings.local.json (로컬 JSON)
- appsettings.json (기본 JSON)
- App.config
- 시스템 환경 변수
- 기본값 (코드에 하드코딩된 값)
📘 상세한 설정 가이드: CONFIGURATION_GUIDE.md 참조
사용 방법
1. 라이브러리 참조
using LoginLibrary.Models;
using LoginLibrary.Services;
using LoginLibrary.Data;
// 사용자 모델 정의
public class MyUser : IUserBase
{
public string UserID { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public DateTime CreatedDate { get; set; }
public string CreatedBy { get; set; }
public DateTime? UpdatedDate { get; set; }
public string UpdatedBy { get; set; }
}
2. DbContext 및 Service 초기화
// DbContext 생성
var context = new LoginDbContext<MyUser>();
// LoginService 생성
// - AuthMode에 따라 JWT 또는 세션 기반 인증 선택
// - Session 모드일 때 SessionStorage에 따라 Memory/Database/Redis 선택
var service = new LoginService<MyUser>(context);
// 이벤트 구독
service.OnLoginSuccess += (s, userId) => Console.WriteLine($"로그인 성공: {userId}");
service.OnUserCreated += (s, user) => Console.WriteLine($"사용자 생성: {user.Email}");
3. 로그인
// 사용자 로그인
// JWT 모드: JWT 토큰 반환
// Session 모드: 세션 ID 반환
var token = await service.LoginAsync("user@example.com", "password123");
if (!string.IsNullOrEmpty(token))
{
Console.WriteLine($"인증 토큰: {token}");
}
4. 토큰/세션 검증
// 토큰 또는 세션 유효성 검증
bool isValid = await service.ValidateSessionAsync(token);
if (isValid)
{
Console.WriteLine("인증 유효");
}
5. 사용자 등록
var newUser = new MyUser
{
UserID = Guid.NewGuid().ToString(),
Email = "newuser@example.com",
Password = "securepassword",
CreatedBy = "Admin"
};
await service.CreateUserAsync(newUser);
JWT 직접 사용
JWT 토큰 관리자를 직접 사용하여 토큰을 생성하고 검증할 수도 있습니다:
using LoginLibrary.Services.Jwt;
// JWT 토큰 관리자 생성
var jwtManager = new JwtTokenManager();
// 토큰 생성
string token = await jwtManager.CreateTokenAsync("user-id-123");
// 토큰 검증
bool isValid = await jwtManager.ValidateTokenAsync(token);
// 토큰에서 사용자 ID 추출
string userId = await jwtManager.GetUserIdFromTokenAsync(token);
// 토큰 무효화 (로그아웃)
await jwtManager.RevokeTokenAsync(token);
OAuth 2.0 인증
LoginLibrary는 주요 OAuth 2.0 프로바이더를 지원합니다:
- Google: Google 계정 인증
- GitHub: GitHub 계정 인증
- Microsoft: Microsoft 개인/조직 계정 인증 (Azure AD)
- Facebook: Facebook 계정 인증
OAuth 설정
환경 변수 또는 설정 파일에서 OAuth 클라이언트 정보를 설정합니다:
# Google OAuth
LoginLibrary__OAuth__Google__ClientId=your-google-client-id.apps.googleusercontent.com
LoginLibrary__OAuth__Google__ClientSecret=your-google-client-secret
# GitHub OAuth
LoginLibrary__OAuth__GitHub__ClientId=your-github-client-id
LoginLibrary__OAuth__GitHub__ClientSecret=your-github-client-secret
# Microsoft OAuth
LoginLibrary__OAuth__Microsoft__ClientId=your-microsoft-client-id
LoginLibrary__OAuth__Microsoft__ClientSecret=your-microsoft-client-secret
LoginLibrary__OAuth__Microsoft__TenantId=common
# Facebook OAuth
LoginLibrary__OAuth__Facebook__ClientId=your-facebook-app-id
LoginLibrary__OAuth__Facebook__ClientSecret=your-facebook-app-secret
# 기본 리다이렉트 URI
LoginLibrary__OAuth__RedirectUri=https://localhost:5001/api/oauth/callback
OAuth 서비스 사용
using LoginLibrary.Services.OAuth;
using LoginLibrary.Utils;
// 1. OAuthService 생성 (ConfigHelper 설정 자동 적용)
var oauthService = OAuthServiceFactory.Create();
// 2. 인증 URL 생성 (사용자를 이 URL로 리다이렉트)
string authUrl = oauthService.GetAuthorizationUrl(
providerName: "Google",
redirectUri: "https://localhost:5001/api/oauth/callback/google",
state: Guid.NewGuid().ToString() // CSRF 방지
);
// 3. OAuth 콜백 처리 (사용자가 인증 후 리다이렉트됨)
OAuthUserInfo userInfo = await oauthService.HandleCallbackAsync(
providerName: "Google",
code: "authorization-code-from-provider",
redirectUri: "https://localhost:5001/api/oauth/callback/google"
);
// 4. 사용자 정보 활용
Console.WriteLine($"이메일: {userInfo.Email}");
Console.WriteLine($"이름: {userInfo.Name}");
Console.WriteLine($"프로필 사진: {userInfo.Picture}");
Console.WriteLine($"프로바이더: {userInfo.Provider}");
Console.WriteLine($"프로바이더 ID: {userInfo.ProviderId}");
OAuth 프로바이더 직접 사용
using LoginLibrary.Services.OAuth;
// Google OAuth 프로바이더 직접 생성
var googleProvider = new GoogleOAuthProvider(
clientId: "your-client-id",
clientSecret: "your-client-secret"
);
// 인증 URL 생성
string authUrl = googleProvider.GetAuthorizationUrl(
redirectUri: "https://localhost:5001/callback",
scope: "openid email profile"
);
// 토큰 교환
var tokenResponse = await googleProvider.ExchangeCodeAsync(
code: "auth-code",
redirectUri: "https://localhost:5001/callback"
);
// 사용자 정보 조회
var userInfo = await googleProvider.GetUserInfoAsync(tokenResponse.AccessToken);
// 토큰 갱신
var newToken = await googleProvider.RefreshTokenAsync(tokenResponse.RefreshToken);
OAuth 이벤트 처리
var oauthService = OAuthServiceFactory.Create();
// 로그인 성공 이벤트
oauthService.OnOAuthLoginSuccess += (sender, args) =>
{
Console.WriteLine($"[{args.ProviderName}] OAuth 로그인 성공!");
Console.WriteLine($" 이메일: {args.UserInfo.Email}");
Console.WriteLine($" 이름: {args.UserInfo.Name}");
};
// 로그인 실패 이벤트
oauthService.OnOAuthLoginFailed += (sender, args) =>
{
Console.WriteLine($"[{args.ProviderName}] OAuth 로그인 실패!");
Console.WriteLine($" 오류: {args.Error}");
Console.WriteLine($" 설명: {args.ErrorDescription}");
};
OAuth 프로바이더 설정 가이드
Google OAuth 설정
- Google Cloud Console 접속
- 새 프로젝트 생성 또는 기존 프로젝트 선택
- "API 및 서비스" > "사용자 인증 정보" 이동
- "사용자 인증 정보 만들기" > "OAuth 클라이언트 ID" 선택
- 애플리케이션 유형: "웹 애플리케이션"
- 승인된 리다이렉트 URI 추가
- 클라이언트 ID와 클라이언트 보안 비밀번호 복사
GitHub OAuth 설정
- GitHub Developer Settings 접속
- "OAuth Apps" > "New OAuth App" 클릭
- 애플리케이션 정보 입력
- Authorization callback URL 설정
- Client ID와 Client Secret 복사
Microsoft OAuth 설정
- Azure Portal 접속
- "Azure Active Directory" > "앱 등록" 이동
- "새 등록" 클릭
- 애플리케이션 정보 입력
- 리다이렉트 URI 추가 (웹)
- "인증서 및 암호"에서 새 클라이언트 암호 생성
- 애플리케이션(클라이언트) ID와 암호 복사
Facebook OAuth 설정
- Facebook Developers 접속
- "내 앱" > "앱 만들기" 클릭
- "소비자" 유형 선택
- 앱 설정에서 "Facebook 로그인" 추가
- 유효한 OAuth 리다이렉트 URI 설정
- 앱 ID와 앱 시크릿 복사
보안
- 비밀번호 해싱: MD5 + Salt (프로젝트 요구사항)
- JWT 토큰: HMAC-SHA256 서명, 환경 변수로 비밀 키 설정
- 세션 관리: 30분 자동 만료 (연장 가능)
- 입력 검증: LoginRequest를 통한 동적 바인딩
- 🆕 Rate Limiting: 로그인 시도 제한 및 점진적 계정 잠금
Rate Limiting (로그인 시도 제한)
LoginLibrary는 무차별 대입 공격(Brute Force Attack)을 방지하기 위한 Rate Limiting 기능을 제공합니다.
주요 기능
- 연속 실패 시 점진적 계정 잠금: 15분 → 30분 → 1시간 → 최대 24시간
- IP 기반 Rate Limiting: 특정 IP에서 과도한 요청 차단
- IP 화이트리스트: 신뢰할 수 있는 IP 주소는 Rate Limiting 제외
- 자동 초기화: 로그인 성공 시 실패 카운터 자동 초기화
Rate Limiting 설정
환경 변수 또는 설정 파일에서 Rate Limiting을 구성할 수 있습니다:
| 설정 키 | 기본값 | 설명 |
|---|---|---|
LoginLibrary:RateLimit:Enabled |
true |
Rate Limiting 활성화 여부 |
LoginLibrary:RateLimit:MaxAttempts |
5 |
최대 로그인 시도 횟수 |
LoginLibrary:RateLimit:WindowMinutes |
15 |
시도 횟수 계산 시간 윈도우 (분) |
LoginLibrary:RateLimit:LockoutMinutes |
15 |
초기 계정 잠금 시간 (분) |
LoginLibrary:RateLimit:WhitelistedIps |
|
IP 화이트리스트 (쉼표 구분) |
Rate Limiting 사용
using LoginLibrary.Services;
using LoginLibrary.Models;
// LoginService는 자동으로 Rate Limiting을 적용합니다
var service = new LoginService<MyUser>(context);
// IP 주소와 함께 로그인 (Rate Limiting 적용)
string token = await service.LoginAsync("user@example.com", "password", "192.168.1.100");
// 상세한 결과를 받는 로그인
LoginResult result = await service.LoginWithResultAsync("user@example.com", "password", "192.168.1.100");
if (result.Success)
{
Console.WriteLine($"토큰: {result.Token}");
}
else if (result.IsAccountLocked)
{
Console.WriteLine($"계정이 잠겼습니다. {result.SecondsUntilRetry}초 후 재시도하세요.");
}
else
{
Console.WriteLine($"로그인 실패. 남은 시도: {result.RemainingAttempts}회");
}
// 계정 잠금 상태 확인
var lockout = await service.GetAccountLockoutAsync("user@example.com");
if (lockout != null)
{
Console.WriteLine($"잠금 해제 시각: {lockout.LockoutEnd}");
}
// 관리자: 계정 잠금 해제
await service.UnlockAccountAsync("user@example.com");
Rate Limiting 이벤트
// 로그인 실패 이벤트
service.OnLoginFailed += (sender, args) =>
{
Console.WriteLine($"로그인 실패: {args.Email}");
Console.WriteLine($"IP: {args.IpAddress}");
Console.WriteLine($"사유: {args.Reason}");
Console.WriteLine($"Rate Limited: {args.IsRateLimited}");
};
// 계정 잠금 이벤트
service.OnAccountLocked += (sender, args) =>
{
Console.WriteLine($"계정 잠금: {args.Email}");
Console.WriteLine($"실패 횟수: {args.FailedAttemptCount}");
Console.WriteLine($"잠금 해제: {args.LockoutEnd}");
};
IRateLimitService 직접 사용
Rate Limiting 서비스를 직접 사용할 수도 있습니다:
using LoginLibrary.Services;
using LoginLibrary.Models;
// 메모리 기반 Rate Limiting (단일 서버용)
IRateLimitService rateLimitService = new MemoryRateLimitService();
// 데이터베이스 기반 Rate Limiting (다중 서버용)
IRateLimitService rateLimitService = new DbRateLimitService<MyUser>(context);
// Rate Limit 확인
var result = await rateLimitService.CheckRateLimitAsync("user@example.com", "192.168.1.100");
if (!result.IsAllowed)
{
Console.WriteLine($"차단됨: {result.DenialReason}");
Console.WriteLine($"재시도까지: {result.SecondsUntilRetry}초");
}
// 로그인 시도 기록
await rateLimitService.RecordLoginAttemptAsync("user@example.com", "192.168.1.100", false, "잘못된 비밀번호");
// 실패 횟수 조회
int failedCount = await rateLimitService.GetRecentFailedAttemptsCountAsync("user@example.com");
// 오래된 기록 정리 (30일 이상)
int cleaned = await rateLimitService.CleanupOldAttemptsAsync(30);
ASP.NET Core DI (의존성 주입)
LoginLibrary는 ASP.NET Core의 의존성 주입을 지원하는 확장 메서드를 제공합니다.
기본 사용법
// Program.cs 또는 Startup.cs
using LoginLibrary.Extensions;
var builder = WebApplication.CreateBuilder(args);
// 기본 설정으로 LoginLibrary 등록
builder.Services.AddLoginLibrary<ApplicationUser>(builder.Configuration);
옵션을 통한 구성
// 커스텀 옵션으로 LoginLibrary 구성
builder.Services.AddLoginLibrary<ApplicationUser>(options =>
{
options.AuthMode = AuthMode.Jwt;
options.SessionStorage = SessionStorageType.Redis;
options.RedisConnectionString = "localhost:6379";
// Rate Limiting 설정
options.RateLimitEnabled = true;
options.RateLimitMaxAttempts = 5;
options.RateLimitWindowMinutes = 15;
options.RateLimitLockoutMinutes = 15;
// JWT 설정
options.JwtSettings = new JwtSettings
{
SecretKey = "your-super-secret-key",
Issuer = "YourApp",
Audience = "YourAppClients",
ExpirationMinutes = 60
};
});
JWT 설정 추가
// JWT 인증 설정만 추가
builder.Services.AddLoginLibraryJwt(jwt =>
{
jwt.SecretKey = builder.Configuration["Jwt:SecretKey"];
jwt.Issuer = builder.Configuration["Jwt:Issuer"];
jwt.Audience = builder.Configuration["Jwt:Audience"];
jwt.ExpirationMinutes = 60;
jwt.RefreshTokenExpirationDays = 7;
});
Rate Limiting 설정 추가
// Rate Limiting 설정만 추가
builder.Services.AddLoginLibraryRateLimiting(rateLimit =>
{
rateLimit.EnableRateLimiting = true;
rateLimit.MaxFailedAttempts = 5;
rateLimit.AttemptWindowMinutes = 15;
rateLimit.InitialLockoutMinutes = 15;
rateLimit.LockoutMultiplier = 2;
rateLimit.MaxLockoutMinutes = 1440; // 24시간
rateLimit.EnableIpBasedRateLimiting = true;
rateLimit.MaxRequestsPerIp = 100;
});
등록된 서비스 사용
// Controller에서 DI를 통해 서비스 주입
[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
private readonly LoginService<ApplicationUser> _loginService;
private readonly IRateLimitService _rateLimitService;
public AuthController(
LoginService<ApplicationUser> loginService,
IRateLimitService rateLimitService)
{
_loginService = loginService;
_rateLimitService = rateLimitService;
}
[HttpPost("login")]
public async Task<IActionResult> Login([FromBody] LoginRequest request)
{
var ipAddress = HttpContext.Connection.RemoteIpAddress?.ToString();
var result = await _loginService.LoginWithResultAsync(
request.Email,
request.Password,
ipAddress);
if (result.Success)
{
return Ok(new { token = result.Token });
}
if (result.IsAccountLocked)
{
return StatusCode(423, new {
message = "계정이 잠겼습니다.",
retryAfter = result.SecondsUntilRetry
});
}
return Unauthorized(new {
message = result.ErrorMessage,
remainingAttempts = result.RemainingAttempts
});
}
}
appsettings.json 설정
{
"LoginLibrary": {
"AuthMode": "Jwt",
"SessionStorage": "Redis",
"RedisConnectionString": "localhost:6379",
"RateLimit": {
"Enabled": true,
"MaxAttempts": 5,
"WindowMinutes": 15,
"LockoutMinutes": 15,
"WhitelistedIps": "127.0.0.1,::1"
},
"Jwt": {
"SecretKey": "YourSuperSecretKeyForJwtToken12345678901234567890",
"Issuer": "YourAppName",
"Audience": "YourAppClients",
"ExpirationMinutes": 60
}
}
}
테스트
콘솔 테스트 앱 실행
dotnet run --project LoginLibrary.TestApp/LoginLibrary.TestApp.csproj
Web API 실행 (Swagger 포함)
dotnet run --project LoginLibrary.WebApi/LoginLibrary.WebApi.csproj
접속: https://localhost:7244/swagger
단위 테스트 실행
dotnet test LoginLibrary.Tests/LoginLibrary.Tests.csproj
주요 클래스
LoginService
핵심 서비스 클래스로, 다음 기능을 제공합니다:
| 메서드 | 설명 |
|---|---|
LoginAsync(email, password) |
사용자 인증 및 토큰/세션 생성 |
LoginAsync(email, password, ipAddress) |
🆕 IP 주소 기반 Rate Limiting 적용 로그인 |
LoginWithResultAsync(email, password, ipAddress) |
🆕 상세 결과를 반환하는 로그인 |
LogoutAsync(sessionId) |
토큰 무효화 또는 세션 제거 (로그아웃) |
CreateUserAsync(user) |
새 사용자 생성 |
UpdateUserAsync(user) |
사용자 정보 수정 |
DeleteUserAsync(userId) |
사용자 삭제 |
ChangePasswordAsync(userId, oldPassword, newPassword) |
비밀번호 변경 |
ValidateSessionAsync(sessionId) |
토큰/세션 유효성 검증 |
GetAccountLockoutAsync(email) |
🆕 계정 잠금 상태 확인 |
UnlockAccountAsync(email) |
🆕 계정 잠금 해제 (관리자용) |
이벤트
public event EventHandler<string> OnLoginSuccess;
public event EventHandler<LoginFailedEventArgs> OnLoginFailed; // 🆕
public event EventHandler<AccountLockedEventArgs> OnAccountLocked; // 🆕
public event EventHandler<string> OnLogoutSuccess;
public event EventHandler<TUser> OnUserCreated;
public event EventHandler<TUser> OnUserUpdated;
public event EventHandler<string> OnUserDeleted;
public event EventHandler<string> OnPasswordChanged;
의존성
- EntityFramework 6.5.1
- NLog 6.0.6
- StackExchange.Redis 2.10.1
- System.Configuration.ConfigurationManager 10.0.0
- Microsoft.Extensions.Configuration 8.0.0
- Microsoft.Extensions.Configuration.Json 8.0.0
- Microsoft.Extensions.Configuration.EnvironmentVariables 8.0.0
- Microsoft.Extensions.DependencyInjection 8.0.0 (🆕 DI 지원)
- Microsoft.Extensions.Options 8.0.0 (🆕 옵션 패턴)
- DotNetEnv 3.1.1
- System.IdentityModel.Tokens.Jwt 8.0.2
- Newtonsoft.Json 13.0.3
라이선스
MIT License
작성자
LoginLibrary Development Team
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET Framework | net472 is compatible. net48 was computed. net481 was computed. |
-
.NETFramework 4.7.2
- DotNetEnv (>= 3.1.1)
- EntityFramework (>= 6.5.1)
- Microsoft.Extensions.Configuration (>= 8.0.0)
- Microsoft.Extensions.Configuration.EnvironmentVariables (>= 8.0.0)
- Microsoft.Extensions.Configuration.Json (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options (>= 8.0.0)
- Newtonsoft.Json (>= 13.0.3)
- NLog (>= 6.0.6)
- StackExchange.Redis (>= 2.10.1)
- System.Configuration.ConfigurationManager (>= 10.0.0)
- System.IdentityModel.Tokens.Jwt (>= 8.0.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.2.0 | 211 | 11/26/2025 |
v1.2.0:
- Rate Limiting 기능 추가 (로그인 시도 제한, 계정 잠금)
- ASP.NET Core DI 확장 메서드 추가 (AddLoginLibrary)
- LoginResult, LoginFailedEventArgs, AccountLockedEventArgs 모델 추가
- IP 기반 Rate Limiting 및 화이트리스트 지원
v1.1.0:
- OAuth 2.0 지원 (Google, GitHub, Microsoft, Facebook)
- 세션 저장소 선택 기능 (Memory, Database, Redis)
v1.0.0:
- 초기 릴리스
- JWT 및 세션 기반 인증
- 사용자 CRUD 작업