LoginLibrary 1.2.0

dotnet add package LoginLibrary --version 1.2.0
                    
NuGet\Install-Package LoginLibrary -Version 1.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="LoginLibrary" Version="1.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="LoginLibrary" Version="1.2.0" />
                    
Directory.Packages.props
<PackageReference Include="LoginLibrary" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add LoginLibrary --version 1.2.0
                    
#r "nuget: LoginLibrary, 1.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package LoginLibrary@1.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=LoginLibrary&version=1.2.0
                    
Install as a Cake Addin
#tool nuget:?package=LoginLibrary&version=1.2.0
                    
Install as a Cake Tool

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

설정 우선 순위 (높음 → 낮음)

  1. 환경별 .env 파일 (.env.production, .env.development 등)
  2. .env.local (개인 로컬 설정)
  3. .env (기본 환경 파일)
  4. appsettings.{Environment}.json (환경별 JSON)
  5. appsettings.local.json (로컬 JSON)
  6. appsettings.json (기본 JSON)
  7. App.config
  8. 시스템 환경 변수
  9. 기본값 (코드에 하드코딩된 값)

📘 상세한 설정 가이드: 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 설정
  1. Google Cloud Console 접속
  2. 새 프로젝트 생성 또는 기존 프로젝트 선택
  3. "API 및 서비스" > "사용자 인증 정보" 이동
  4. "사용자 인증 정보 만들기" > "OAuth 클라이언트 ID" 선택
  5. 애플리케이션 유형: "웹 애플리케이션"
  6. 승인된 리다이렉트 URI 추가
  7. 클라이언트 ID와 클라이언트 보안 비밀번호 복사
GitHub OAuth 설정
  1. GitHub Developer Settings 접속
  2. "OAuth Apps" > "New OAuth App" 클릭
  3. 애플리케이션 정보 입력
  4. Authorization callback URL 설정
  5. Client ID와 Client Secret 복사
Microsoft OAuth 설정
  1. Azure Portal 접속
  2. "Azure Active Directory" > "앱 등록" 이동
  3. "새 등록" 클릭
  4. 애플리케이션 정보 입력
  5. 리다이렉트 URI 추가 (웹)
  6. "인증서 및 암호"에서 새 클라이언트 암호 생성
  7. 애플리케이션(클라이언트) ID와 암호 복사
Facebook OAuth 설정
  1. Facebook Developers 접속
  2. "내 앱" > "앱 만들기" 클릭
  3. "소비자" 유형 선택
  4. 앱 설정에서 "Facebook 로그인" 추가
  5. 유효한 OAuth 리다이렉트 URI 설정
  6. 앱 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 Compatible and additional computed target framework versions.
.NET Framework net472 is compatible.  net48 was computed.  net481 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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 작업