백엔드 개발/인증 · 보안
[Node.js] 중복 로그인 어떻게 막을까? JWT + Redis 실무 구현 예시
JeongPark
2023. 7. 5. 22:31
728x90
[Node.js] 중복 로그인 처리하기 – 실무에서 세션 제어하는 방법
서비스를 운영하다 보면 "동일 계정으로 동시에 여러 기기에서 로그인"되는 문제를 제어하고 싶을 때가 있습니다.
보안이 중요한 서비스라면 중복 로그인 방지 처리가 필수죠.
목표
- 한 계정으로 로그인했을 때, 기존 세션이 존재하면 처리 방식 결정
- 이전 세션 강제 만료
- 중복 로그인 차단
- Redis + JWT + Node.js로 구현
전제 조건
- JWT 기반 인증 (
accessToken
,refreshToken
) - 로그인 시 Redis에 refreshToken 저장
- 인증 시 Redis 내 토큰과 일치 여부 검증
예시 코드 – 로그인 시 토큰 발급 및 중복 확인
// 로그인 서비스 예시
import { getRefreshToken, saveRefreshToken } from './redis';
export const loginUser = async (email: string, password: string) => {
const user = await userRepository.findOne({ where: { email } });
if (!user) throw new Error('존재하지 않는 사용자입니다.');
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) throw new Error('비밀번호가 일치하지 않습니다.');
const refreshToken = generateRefreshToken(user.id); // 새 토큰 발급
const existing = await getRefreshToken(user.id);
if (existing) {
// 이미 로그인된 사용자 (중복 로그인 처리)
// 방법 1: 기존 토큰 삭제 → 새로운 세션만 유지
await saveRefreshToken(user.id, refreshToken);
// 방법 2: 에러 반환 → 중복 로그인 차단
// throw new Error('이미 로그인된 세션이 존재합니다.');
} else {
await saveRefreshToken(user.id, refreshToken);
}
const accessToken = generateAccessToken(user.id);
return { accessToken, refreshToken };
};
중복 로그인 처리 전략
전략 | 설명 |
---|---|
기존 세션 무효화 | 새 로그인 시 이전 세션(리프레시 토큰) 삭제 |
중복 로그인 차단 | 이미 존재하면 새 로그인 거부 |
병행 허용 | 여러 토큰 저장 (추가 구현 필요) |
Redis에 저장 구조 예시
// 키: userId, 값: refreshToken
await redis.set(`refresh:${userId}`, token, { EX: 60 * 60 * 24 * 7 }); // 7일 만료
실무 팁
- 단말별 로그인 허용이 필요하면 deviceId 기반 구조로 확장
- 로그아웃 시에도 Redis에서 토큰 삭제 필수
- 강제 로그아웃 시 WebSocket, SSE 연동 가능
결론
- 중복 로그인 처리 여부는 서비스 정책에 따라 다르게 설계해야 함
- Redis + JWT 조합으로 간단하게 구현 가능
- 확장이 필요하면 device-level, IP, location 등을 고려해 추가 설계 가능
반응형