[TIL 64일 차] 유저 관리 기능

유저 관리 기능

1. 유저 기능 이해와 인증 개념

1-01. 유저 기능의 필요성과 활용

유저(User) 기능은 개인별로 식별 가능한 계정을 통해 서비스를 이용할 수 있게 하는 역할

유저 기능을 통해 사용자별로 다른 경험을 제공할 수 있음. 이걸 개인화(Personalization)라고 함.

  • 예시:
    • 넷플릭스: 사용자의 시청 기록과 취향에 맞는 영화 추천
    • 쿠팡: 자주 구매한 상품, 배송 주소, 결제 수단이 자동으로 불러와짐
    • 유튜브: 로그인 시 개인 구독 목록과 추천 영상이 불러와짐


1-02. 인증(Authentication)

유저 기능을 구현할 때 가장 중요한 과정으로, 사용자가 누구인지 확인하는 과정이다. 즉, 시스템이 특정 사용자가 본인이 맞는지를 검증하는 과정이다.


1) 목적

  • 시스템 접근 제어
  • 개인정보 보호
  • 비인가 사용자 차단
  • 사용자별 맞춤 서비스 제공


2) 인증 방식

  • ID + Password
    • 예시
    • “이메일 + 비밀번호” - 가장 기본적인 인증 방식
      • 단순 비교가 아니라 암호화된 값 비교와 추가 인증 관리가 필요함
        • 입력된 Password를 해시(Hash) 처리하여 저장된 해시 값과 비교
        • 실패 횟수 관리 ➡️ 계정 잠금
        • 성공 시 세션/토큰 발급
  • 소셜 로그인
  • 2단계 인증(2FA)
  • 생체 인증


3) 인증? 인가?

  • 인증(Authentication) : 사용자가 본인임을 확인하는 과정
  • 인가(Authorization) : 인증된 사용자가 무엇을 할 수 있는지 결정하는 절차
    • 특정 자원에 접근할 수 있는 권한을 확인
  • 예시
    • 로그인 시 ➡️ 인증 (본인 확인)
    • 송금 가능 여부 확인 시 ➡️ 인가 (권한 확인)


4) 인증 정보 관리

.../
   └─ user/
       ├─ User.java             # 유저 엔티티 클래스
       ├─ UserProfile.java      # 유저 프로필 (닉네임, 나이 등)
       └─ UserCredential.java   # 인증 정보 (비밀번호, 로그인 시도 기록 등)
import java.time.LocalDateTime;

public class User {
    private Long id;                  // 고유 ID
    private String email;             // 이메일 (로그인 ID)
    private UserProfile profile;      // 프로필 정보
    private UserCredential credential;// 인증 정보
    private String role;              // 권한 (예: USER, ADMIN)
    private LocalDateTime createdAt;  // 계정 생성일

    // 생성자, getter, setter 생략
}
import java.time.LocalDateTime;

public class UserCredential {
    private String passwordHash;          // 암호화된 비밀번호
    private int failedLoginAttempts;      // 로그인 실패 횟수
    private LocalDateTime lastLoginAt;    // 마지막 로그인 시각
    private boolean locked;               // 계정 잠금 여부
}


1-03. 인증 상태 유지

인증 상태 유지가 필요한 이유는 HTTP 프로토콜의 속성인 무상태성(stateless) 때문

HTTP 서버는 각 요청을 기본적으로 독립적인 요청으로 처리하므로, 사용자가 한 번 로그인했다고 해서 이후 요청에서도 자동으로 신원이 유지되는 것이 아니다.

➡️ 세션 또는 토큰 같은 메커니즘으로 “누가 요청했는가”매 요청마다 증명해야 한다.


1) 필요성-HTTP 속성

  • 무상태성(stateless) : 이전 요청의 맥락(로그인 여부, 사용자 정보)을 자동으로 기억하지 않음
  • 연결 재사용과 무관 : HTTP keep-alive로 TCP 연결을 재사용하더라도, 그것이 로그인 상태 유지를 의미하지는 않음
  • 분산 인프라 특성 : 로드 밸런서, 다수의 서버, 프록시가 실제 서비스에 개입하기 때문에 서버 로컬 메모리에만 의존하면 다른 서버로 라우팅되는 순간 인증 상태를 잃어버림
  • 보안 경계의 일관성 : 매 요청마다 신원 확인이 가능해야 함


2) 상태를 유지하는 대표 전략 두 가지

  • 세션 기반 방식 (쿠키)
    • 로그인 성공 시 서버가 세션 ID를 생성하고, 이를 쿠키로 클라이언트에 전달한다. 이후 요청마다 쿠키로 세션을 찾아 사용자 신원을 복원한다.
  • 토큰 기반 방식 (JWT 등)
    • 로그인 성공 시 서명이 포함된 토큰을 발급한다. 클라이언트는 이후 요청마다 토큰을 Authorization 헤더로 전송하고, 서버는 서명 검증으로 신원을 확인한다.

2. 쿠키와 세션 기반 인증

2-01. 쿠키의 개념과 특성

쿠키(Cookie)는 브라우저가 보관하고 요청마다 자동 전송하는 작은 데이터

서버는 쿠키를 활용해 무상태(stateless)인 HTTP에서 사용자의 상태(로그인 여부 등)를 복원


1) 쿠키의 구조와 속성

  • 기본 형태 : name=value
  • 속성 : 세미콜론(;)으로 구분된 Key=Value 또는 플래그
  • 민감한 정보가 담긴 쿠키에는 HttpOnly + Secure + SameSite를 기본값으로 적용
Set-Cookie: SESSIONID=abc123;
Path=/;
Domain=example.com;
Max-Age=1800;
HttpOnly; Secure;
SameSite=Lax
속성 의미 주요 포인트
Name=Value 쿠키 이름과 값 값에는 공백, 세미콜론 등 특수문자 금지. 필요 시 URL 인코딩 권장
Domain 쿠키가 전송될 도메인 범위 미설정 시 호스트 전용. 설정 시 해당 도메인 및 하위 도메인에 전송
Path 전송 경로 제한 접두 경로(prefix) 매칭. 보통 / 권장
Expires 만료 시각(절대) 표준화된 GMT 날짜 문자열
Max-Age 만료까지 남은 시간(초) Max-Age가 있으면 Expires보다 우선
Secure HTTPS 연결에서만 전송 민감한 쿠키는 필수
HttpOnly JS 접근 차단 XSS 완화. 인증 쿠키에 강력 권장
SameSite 크로스 사이트 전송 제어 Lax 기본, SSO나 외부 리디렉션은 None+Secure 필요
Priority(브라우저별) 제거 우선순위 힌트 용량 초과 시 폐기 우선순위에 영향
  • 쿠키 이름 접두사 | 접두사 | 요구 조건 | 효과 | | ———– | ————————————– | ———————————————– | | __Secure- | Secure 필수 | 보안 전용임을 표현하는 관례 | | __Host- | Secure 필수, Path=/, Domain 금지 | 호스트 고정. 하위 도메인 오남용 차단에 유용 |


2) 브라우저의 쿠키 처리 흐름

  • 도메인/경로 매칭에 부합하는 요청에만 자동 전송
  • 동일 이름의 쿠키가 경로(Path)나 도메인(Domain)에 따라 여러 개가 동시에 존재 가능


3) 생명주기와 용량 제한

  • 세션 쿠키: Expires / Max-Age 미지정. 브라우저 종료 시 삭제
  • 영속 쿠키: 만료 정보 지정. 지정 시간까지 유지
  • 용량: 브라우저마다 다르나 쿠키 하나 약 4KB, 도메인당 수십 개 수준이 일반적


4) 도메인과 경로 매칭 규칙

  • Domain 미설정 : 정확히 일치하는 호스트에서만 전송
  • Domain=example.com 설정 : sub.example.com 포함 하위 도메인에도 전송
  • Path=/account: /account와 그 하위 경로에만 전송

권장: 인증 쿠키는 “호스트 전용 + Path=/ + __Host-접두사”로 범위를 최소화


2-02. 세션 기반 인증의 이해

1) 세션(Session)이란?

클라이언트(사용자)가 서버에 접속한 순간부터 접속을 끊을 때까지의 연결 상태를 의미함

웹에서는 HTTP 프로토콜이 무상태(stateless)이므로 서버가 사용자의 상태를 기억하지 못함. 세션을 사용하면 사용자의 상태 정보를 서버에 저장해두고, 이를 세션 ID(Session ID)라는 키로 식별하는 방식


2) 세션의 특징

  • 서버 중심 관리 : 사용자 로그인 여부, 권한, 장바구니 정보 등을 서버가 직접 보관
  • 클라이언트는 세션 ID만 보관 : 브라우전느 세션을 가리키는 고유한 ID를 쿠키에 저장
  • 만료 가능 : 일정 시간 동안 요청이 없으면 세션 종료, 최대 사용 시간 설정 가능
  • 보안 의존성 : 세션 ID가 유출되면 사용자 정보가 탈취될 수 있다.


3) 세션 생성과 전달, 확인 과정

  • 세션 생성과 전달
    1. 사용자 로그인 ➡️ 아이디/비밀번호 검증 수행
    2. 검증 성공 ➡️ 서버는 새로운 세션(Session) 객체 생성 ➡️ 사용자 ID와 관련 정보를 세션 저장소에 저장
    3. 서버는 해당 세션을 식별할 수 있는 세션 ID 생성
    4. 생성된 세션 ID를 Set-Cookie 헤더에 담아 브라우저에 전달

      HTTP/1.1 200 OK
      Set-Cookie: SESSION=abc123; Path=/; HttpOnly; Secure; Max-Age=1800
      
  • 세션 확인 과정
    1. 사용자가 보호된 페이지에 접근 ➡️ 브라우저는 자동으로 요청에 Cookie 헤더를 포함
    2. 서버는 요청 헤더의 세션 ID 확인 ➡️ 세션 저장소에서 해당 세션 ID를 찾아 사용자 정보 복원
    3. 유효한 세션일 때 요청을 정상 처리하고 응답

      GET /mypage HTTP/1.1
      Host: example.com
      Cookie: SESSION=abc123
      
  • 동작 workflow 다이어그램


4) 세션 기반 인증의 보안 고려사항

  • 세션 ID 보안
    • 랜덤성: 세션 ID는 충분히 긴 난수(예시: UUID v4)를 사용
    • 예측 불가능성: 예측 가능한 단순 숫자 증가나 시간 기반 ID는 금지
    • 쿠키 보안 속성 적용
      • Secure : HTTPS 연결에서만 전송
      • HttpOnly : JavaScript로 쿠키 접근 차단 ➡️ XSS 완화
      • SameSite : 크로스 사이트 오쳥 제한 ➡️ CSRF 완화
  • 세션 만료 정책
    • 유후 타임아웃(Idle Timeout): 일정 시간 요청이 없으면 세션을 자동 만료 시킴
    • 절대 타임아웃(Absolute Timeout): 세션이 생성된지 일정 시간이 지나면 무조건 만료 시킴
    • 강제 로그아웃: 관리자가 특정 사용자의 세션을 강제 만료 시킬 수 있어야 함
  • 세션 고정(Session Fixation) 방지
    • 로그인 성공 시 새로운 세션 ID를 무조건 재발급
  • 로그아웃 처리
    • 서버 측 세션 무효화: 세션 저장소에서 해당 세션 ID 삭제
    • 클라이언트 쿠키 만료 지시: Max-Age=0 또는 Expires 속성을 통해 브라우저 쿠키 제거
    • 즉시 반영: 로그아웃 요청 시 즉시 세션 무효화되어야 하며, 남아있는 요청이 더 이상 인증되지 않아야 함.
  • 추가 고려사항
    • 동시 세션 제어: 동일 사용자가 여러 기기에서 로그인할 경우 정책적으로 허용/제한할지 결정
    • 세션 하이재킹 대응: 비정상적인 위치(IP, User-Agent 등)에서 세션 접근 시 알림 또는 강제 만료 처리
    • 로그 및 모니터링: 로그인/로그아웃, 세션 만료, 실패 시도 등을 로깅하여 추적
    • 전송 계층 보안: 세션 쿠키는 반드시 TLS(HTTPS)를 통해서만 전송
      • TLS는 클라이언트와 서버 사이의 통신을 암호화해 중간에서 데이터가 도청되거나 변조되는 것을 막는 보안 프로토콜
      • HTTPS는 HTTP 통신에 TLS를 적용한 방식


2-03. 쿠키와 세션 보안 설정

1) Secure 설정

Secure 속성은 요청이 암호화된 연결(HTTPS)에서만 쿠키가 전송되도록 제한

  • 네트워크 구간에서 쿠키가 노출될 위험(중간자 공격, 스니핑)을 크게 줄여 줌
  • 서비스 전체가 HTTPS를 사용해야 함
  • 운영 환경에서는 HSTS(HTTP Strict Transport Security)도 함께 고려
    • HSTS는 클라이언트(브라우저)에게 “이 도메인인 무조건 HTTPS로만 접속해야 한다”라는 정책을 전달하는 HTTP 응답 헤더
      Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
      
  • 운영 환경에서는 HTTPS 강제 리다이렉트HSTS를 함께 적용함
  • Secure 예시

    HTTP/1.1 200 OK
    Set-Cookie: SESSION=abc123; Path=/; Secure; HttpOnly; SameSite=Lax; Max-Age=1800
    
  • Secure 동작의 workflow


2) HttpOnly 설정

HttpOnly브라우저 JavaScript(document.cookie)로 쿠키 접근을 차단

  • XSS로부터 쿠키 읽기를 어렵게 만들어 세션 탈취를 완화
    • XSS 자체는 없애지 않음
    • 단지 쿠키 탈취를 막아줄 뿐, DOM 조작 등은 가능함
  • 인증에 쓰이는 모든 쿠키는 기본값으로 사용함
  • HttpOnly 예시
    Set-Cookie: SESSION=abc123; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=1800
    
  • HttpOnly 효과의 workflow


3) SameSite 설정

SameSite다른 사이트에서 오는 요청에 쿠키가 자동으로 첨부되는지 제어하여 CSRF를 완화

  • 옵션
    • Strict : 크로스 사이트 모든 네비게이션에서 쿠키 미전송
      • 소셜 로그인, 외부 리다이렉션 시 불편 ⬆️
    • Lax : 대부분의 크로스 사이트 요청에서 미전송, 탑 레벨 GET 네비게이션은 예외
      • form POST, XHR, iframe 요청은 미전송
    • None : 출처 상관없이 전송
      • 반드시 Secure 동반
  • 예시
    Set-Cookie: SESSION=abc123; Path=/; Secure; HttpOnly; SameSite=Lax
    
  • SameSite 효과 workflow


4) CSRF 공격 예방을 위한 설정

SameSite만으로 충분하지 않은 경우가 많음. 토큰 기반 방어를 함께 적용해야 함.

  • CSRF (Cross-Site Request Forgery)
    • 사용자가 자신도 모르게 공격자가 의도한 요청을 특정 웹 애플리케이션에 보내도록 속이는 공격
    • 원리 : 피해자가 로그인하여 인증 쿠키를 보유 중일 때, 공격자가 조작된 링크나 form을 열게 하면 브라우자가 자동으로 쿠키를 첨부하여 서버에 요청을 보냄
    • workflow

  • 방어 전략
    • 동기화 토큰 (Synchronizer Token)
      • 서버가 세션별 CSRF 토큰 발급, form과 함께 제출
      • 서버 저장소에 토큰 보관 후 일치 여부 검증
      • workflow

    • 더블 서브밋 (Double Submit Cookie)
      • 쿠키로 CSRF 토큰 별도 발급, 본문/헤더 값과 비교
      • 서버는 값 비교만, 저장 불필요(서명 권장)
      • workflow

    • SameSite
      • 크로스 사이트 자동 쿠키 전송 제한

Leave a comment