# 안전한 Rust 인증 서비스 구축: 토큰, 암호화, Redis
Rust로 견고한 인증 서비스를 만드는 데는 암호학, 토큰 관리, 그리고 영리한 추상화에 대한 탄탄한 이해가 필요합니다. 이 글에서는 JWT와 불투명 토큰 생성, 검증, Redis 저장을 다루며 실전 경험을 공유합니다.
토큰 아키텍처와 생성
서비스는 두 가지 토큰 유형을 사용합니다: 짧은 세션을 위한 액세스 토큰(JWT)과 재인증 없이 원활한 갱신을 위한 리프레시 토큰(불투명 토큰).
JWT 토큰은 RS256 알고리즘으로 비대칭 암호화를 사용하며, 서명에는 개인 키, 검증에는 공개 키가 필요합니다. 불투명 토큰은 클라이언트가 읽을 수 없는 무작위 base64 문자열로, 보안을 강화합니다.
키 생성 구성 요소
- JwtTokenProvider: 클레임과 개인 키를 사용한 JWT 생성 트레이트.
- OpaqueTokenProvider: 무작위 바이트를 통한 불투명 토큰 트레이트.
- Claims 구조체: sub(사용자 ID), jti(토큰 ID), iat(발급 시각), exp(만료 시각) 등의 표준 필드 포함.
JwtTokenProvider 구현 예시:
pub trait IJwtTokenProvider {
type Claims: Send + Sync;
type Error;
fn generate(&self, claims: &Self::Claims, pem: &str) -> Result<String, Self::Error>;
}
토큰 검증과 유효성 검사
JWT 검증은 공개 키를 사용해 유출된 개인 키를 차단합니다. IJwtTokenValidator 트레이트가 서명 검사와 토큰 무결성을 처리합니다.
검증 주요 포인트
- PEM 형식: PEM 파일에 키 저장, 인증서와 신뢰 체인 지원.
- 암호화 알고리즘: 대칭(예: HS256)과 비대칭(예: RS256) 지원, 후자를 보안상 선호.
- 클레임 변환: 라이브러리 호환성을 위해 도메인 클레임 모델을 DateTime에서 usize로 변환 등.
검증 코드 예시:
pub trait IJwtTokenValidator {
type Claims: Send + Sync;
type Error;
fn verify(&self, token: &str, pem: &str) -> Result<Self::Claims, Self::Error>;
}
토큰 저장과 오케스트레이션
TokenManager와 KeyManager가 토큰과 키를 관리합니다. TokenManager는 생성, 검증, Redis 저장을 유연한 추상화로 처리합니다.
RedisIO 구현
RedisIO는 setex, get, delete 메서드로 저장 작업을 단순화해 보일러플레이트를 줄이고 가독성을 높입니다.
예시:
impl<Storage> RedisIO<Storage>
where Storage: redis::AsyncCommands + Send + Sync
{
pub async fn setex(&mut self, key: &str, data: &str, exp: u64) -> Result<(), redis::RedisError> {
self.redis_storage.set_ex::<&str, String, (>(&key, data.to_string(), exp).await?;
Ok(())
}
}
TokenManager 기능
제네릭으로 제공자와 검증기를 사용해 쉽게 교체 가능. 주요 메서드:
- generate_pair: 액세스/리프레시 쌍 생성, Redis에 TTL과 함께 저장.
- verify_access: 액세스 토큰 존재와 무결성 검증.
사용 예시:
pub async fn generate_pair(&mut self, claims: &Claims, pem: &str) -> Result<(String, String), TokenManagerError> {
let access_token = self.access_provider.generate(&claims, &pem)?;
let refresh_token = self.refresh_provider.generate();
// Redis 저장 로직
Ok((access_token, refresh_token))
}
주요 요점
- JWT에 RS256 비대칭 암호화가 대칭 방식보다 보안 우수.
- 불투명 토큰은 무작위 base64 문자열로 위조 방지.
- 트레이트로 테스트와 교체 용이.
- Redis TTL 저장으로 세션 효율 관리, DB 부하 감소.
- 개인/공개 키 엄격 분리로 침해 방지.
흔한 함정과 해결책
개발 중 발견된 문제:
- Base64 팽창: 32바이트가 43바이트로 늘어 저장 오류 발생 가능.
- 키 오용: 검증에 개인 키 사용 금지.
- 타입 불일치: DateTime을 usize로 변환 시 유효성 검사 필요.
해결책:
- 다양한 데이터 크기로 엣지 케이스 테스트.
- 키 타입/형식 엄격 검사.
- 검증된 JWT/암호화 라이브러리 활용.
— Editorial Team
아직 댓글이 없습니다.