프로젝트를 위해 웹페이지에 사용자에 대한 인증/인가를 구현해야 했다.

이번 글에서는 HTTP의 특성과 함께 쿠키, 세션, 토큰의 개념을 이해하고 이를 웹 인증/인가에 활용하는 방법을 알아보려고 한다.

HTTP

HTTP(Hypertext Transfer Protocol)는 웹에서 데이터를 주고받기 위한 프로토콜로, 다음과 같은 특성을 가지고 있다.

  • 클라이언트-서버: 클라이언트가 요청을 보내면 서버가 응답을 보내는 구조
  • 무상태성(Stateless): HTTP는 각 요청이 독립적이며, 이전 요청의 상태를 저장하지 않음
  • 비연결성(Connectionless): HTTP는 요청과 응답이 완료되면 연결이 끊어지며, 매 요청마다 새로운 연결을 맺음

이러한 특성 때문에 웹앱에서는 추가적인 방법을 사용하여 상태를 유지하고 사용자 인증을 관리해야 한다.

쿠키

쿠키는 웹 브라우저에 의해 클라이언트 측에 저장되는 작은 데이터 조각이다. 주로 사용자의 세션을 유지하거나 사용자 설정을 기억하는 데 사용된다. 서버는 HTTP 응답 헤더에 Set-Cookie 헤더를 포함하여 쿠키를 설정하고, 브라우저는 쿠키를 저장해 동일한 서버에 재 요청 시 저장된 데이터를 함께 전송한다.

Set-Cookie: sessionId=abc123; Path=/; HttpOnly; Secure

 

장점

  • 간단한 상태 유지
  • 클라이언트 측 저장으로 서버 자원 절약

단점

  • 보안에 취약함
  • 크기 제한 (최대 4KB)

쿠키는 단독으로 인증 방식으로 사용되지는 않으며, 주로 세션과 함께 사용된다. 서버는 사용자 인증 정보를 세션에 저장하고, 세션 ID를 쿠키에 저장하여 클라이언트와 서버 간의 인증 상태를 유지한다.

또한, 쿠키는 웹 브라우저에 의존하기 때문에 네이티브 애플리케이션에서는 사용할 수 없다. 네이티브 애플리케이션에서는 주로 토큰 기반의 인증 방식을 사용한다.

세션

세션은 서버 측에 사용자 정보를 저장하는 방법으로, 주로 사용자 로그인 상태를 유지하는 데 사용된다. 로그인, 로그아웃 시 별도 사용자로 인식하여 새로운 세션을 생성하며, 세션 ID를 통해 세션을 관리한다.

{
  "sessionId": "abc123",
  "userId": "user123",
  "loginTime": "2024-05-23T12:00:00",
  "expiryTime": "2024-05-23T13:00:00",
  "userData": {
    "username": "example_user",
    "email": "user@example.com",
    "role": "user"
  }
}

 

장점

  • 보안성이 높음 (서버에서 관리)
  • 다양한 인증 및 인가 메커니즘을 지원

단점

  • 서버 부담이 큼
  • 확장성 문제 (서버 분산 시 관리가 어려움)

토큰

토큰은 사용자 인증 정보를 포함한 문자열로, 주로 API 인증에 사용된다. 토큰은 서버에서 생성되지만 클라이언트 측에 저장되어 서버에 전달된다. 대표적으로 JWT와 OAuth 토큰이 있다.

1) JWT (JSON Web Token)

JWT는 JSON 포맷을 사용한 토큰으로, Base64로 인코딩된 헤더, 페이로드, 서명으로 구성된다.

{
  "header": {
    "alg": "HS256",
    "typ": "JWT"
  },
  "payload": {
    "sub": "1234567890",
    "name": "John Doe",
    "admin": true
  },
  "signature": "HMACSHA256(
    base64UrlEncode(header) + '.' +
    base64UrlEncode(payload),
    secret)"
}

2) OAuth 토큰

OAuth 프로토콜에서 사용되는 토큰으로, Access 토큰과 Refresh 토큰으로 구분된다.

Access 토큰은 일반적인 API 통신 시 사용되며, 유효기간이 짧다. Refresh 토큰은 Access 토큰의 갱신 시 사용된다.

GET /authorize?
  response_type=code&
  client_id=CLIENT_ID&
  redirect_uri=REDIRECT_URI&
  scope=read write&
  state=STATE

 

장점

  • 확장성
  • 클라이언트 측 저장으로 서버 자원 절약

단점

  • 토큰 탈취 시 악용 가능

페이지 요청 시, 서버는 해당 토큰이 유효한지만 검증하면 되므로 상태를 유지할 필요가 없다. (Stateless)

쿠키, 세션, 토큰 비교

  쿠키 (Cookie) 세션 (Session) 토큰 (Token)
저장 위치 클라이언트 (브라우저) 서버 클라이언트 (브라우저)
데이터 크기 제한 있음 (최대 4KB) 제한 없음 제한 없음 (HTTP 헤더에 포함)
보안성 낮음 (클라이언트 조작 가능) 높음 (서버에서 관리) 높음 (서명 및 암호화 가능)
유효 기간 만료 시간 설정 가능 브라우저 종료 또는 서버 설정 시간 만료 시간 설정 가능
사용 용도 로그인 상태 유지, 사용자 설정 저장 사용자 인증 및 권한 부여 사용자 인증 및 권한 부여
전송 방법 HTTP 요청 시 자동 전송 서버에서 직접 관리 HTTP 요청 시 헤더에 포함

 

이번 글을 통해 HTTP의 특성과 함께 쿠키, 세션, 토큰의 개념을 이해하고 이를 웹 인증/인가에 어떻게 활용할 수 있는지 살펴보았다. 상황에 맞는 적합한 방식을 선택하여 안전하고 효율적인 인증 시스템을 구현하기 바란다.

RESTful API란?

RESTful API는 Representational State Transfer 아키텍처 스타일을 따르는 API를 의미한다.

이는 다음과 같은 구성 요소와 스타일을 가지고 있다.

 

REST의 구성요소

  • 자원(Resource): URI
  • 행위(Verb): HTTP Method (CRUD Operation)
  • 표현(Representation): Payload

CRUD Operation

  • Create: 데이터 생성(POST)
  • Read: 데이터 조회(GET)
  • Update: 데이터 수정(PUT, PATCH)
    • PUT: 데이터 전체 수정
    • PATCH: 데이터 일부 수정
  • Delete: 데이터 삭제(DELETE)

REST를 구성하는 스타일

  1. Client-Server (클라이언트-서버 구조)
  2. 무상태성 (Stateless)
  3. 캐시 처리 가능 (Cacheable)
  4. 계층화 (Layered System)
  5. 인터페이스 일관성 (Uniform Interface)
    • 리소스가 URI로 식별
    • 리소스의 표현을 HTTP 메시지에 담아 전송
    • self-descriptive
    • HATEOAS
  6. Code-on-demand(optional)

HATEOAS

  • Hypermedia As The Engine Of Application State
  • Hypermedia(링크)를 통해 애플리케이션의 상태 전이가 가능해야 한다.
  • 각 요청의 응답에, 가용한 다른 요청들의 정보를 포함한다.
  • 클라이언트는 서버의 상태와 행동을 알 필요가 없으며, 서버 측의 변경에도 클라이언트에선 일일이 대응하지 않아도 된다.

REST API 설계 규칙

  1. 동사보다는 명사를, 대문자보다는 소문자를 사용하여야 한다.
  2. 슬래시 구분자(/)는 계층 관계를 나타내는데 사용한다.
  3. 마지막에 슬래시(/)를 포함하지 않는다.
  4. 언더바(_) 대신 하이픈(-)을 사용한다.
  5. 파일확장자는 URI에 포함하지 않는다.
  6. 행위(CRUD)를 포함하지 않는다.

검색 및 필터링:

  • 특정 조건으로 필터링할 때는 Query parameter나 Pagination을 활용한다.

 

[참고]

[네트워크] REST API란? REST, RESTful이란?

HATEOAS까지 사용해야 완벽한 RESTful이다.

Day1, 2-2. 그런 REST API로 괜찮은가

 

우리가 웹 브라우저의 주소창에 'naver.co' , 'google.co' 또는 'gogle.com' 을 입력하더라도 정상적인 페이지로 이동한다. 왜 그럴까?

이를 이해하기 위해서는 먼저 DNS와 URL리다이렉션에 대한 기본적인 이해가 필요하다.

 

DNS(Domain Name Server)는 쉽게말해 인터넷의 주소록같은 서버이다.

사람들이 기억하기 쉬운 도메인 이름을 컴퓨터가 이해할 수 있는 IP주소로 변환해주는 역할을 한다.

이 과정은 우리가 웹사이트에 접속할때 자동으로 일어나며, 원하는 웹 페이지를 찾아가는데에 필수적이다.

DNS 서버 확인

 

nslookup 명령어를 사용하면 현재 사용하고 있는 DNS 서버를 확인할 수 있다. 

여기서 bns1.hnanet.net 은 SK Broadband의 DNS서버이다.

 

URL 리다이렉션은 사용자가 특정 웹페이지에 접속하려고 할 때, 그 요청을 다른 페이지로 넘겨주는 과정을 말한다.

예를 들어 웹사이트 주소가 변경되었거나 URL 단축 서비스를 사용할 때 사용할 수 있다.

또한, 앞서 제시한 것처럼 사용자가 도메인 이름을 잘못 입력했을 경우에도 올바른 웹사이트로 유도할 수 있는 방법이다.

이때 리다이렉션은 서버가 HTTP 응답 코드 중 3XX 코드를 응답할 때 일어난다.

 

이제 'google.co', 'gogle.com'가 'www.google.com'으로 자동으로 리다이렉트 되는 과정을 살펴보자.

  1. 사용자가 웹 브라우저에 'google.co' 또는 'gogle.com'을 입력한다.
  2. 브라우저는 DNS 시스템을 통해 도메인 이름에 해당하는 IP 주소를 조회한다. 
  3. 일반적으로 'google.co', 'gogle.com' 등은 'www.google.com'으로 리다이렉트하는 규칙이 설정된 도메인이다.
  4. 따라서 사용자의 웹 브라우저는 해당 IP 주소의 서버로 연결을 시도하고, 설정된 리다이렉션 규칙에 따라 HTTP 응답 코드와 함께 최종 목적지 URL('www.google.com')로 안내한다.

말하자면 'google.co', 'gogle.com' 같은 도메인을 'www.google.com'으로 리다이렉트 할 수 있도록 구글이 미리 등록해놓았다는 것이다.

알고보면 간단한 과정이다.

웹 서버 상호작용 확인

 

curl 명령어를 사용하여 어떻게 웹 서버와 상호작용하여 리다이렉션 되는지 확인할 수 있다. (-I 옵션: 헤더정보만 확인)

 

이처럼 DNS와 URL 리다이렉션은 사용자의 편의성을 증진시키지만 악의적인 공격에 노출될 여지가 있는데, DNS 스푸핑과 같은 악의적인 리다이렉션을 통해 사용자는 자신도 모르는 사이에 개인 정보를 노출시키거나 악성 콘텐츠에 노출될 위험이 있다.

이러한 리다이렉션은 사용자가 의심하지 않는 한 쉽게 감지하기 어렵기 때문에 사용자는 항상 웹사이트의 URL을 주의 깊게 확인해야 하며, 특히 URL 단축 서비스(bit.ly 등)를 사용한 단축 URL에 접속하는 경우 해당 링크를 검증하고 확인할 필요가 있다.

+ Recent posts