프로그래머스 풀스택 25

  • programmers

posted on 25 Sep 2024 under category programmers in series programmers

프로그래머스 풀스택 25

백엔드 심화: 인증과 비동기처리(6)

🌊 next(), channels.js validate 정리

💫 next()
alt text

validate 미들웨어 분리:
validate 함수는 유효성 검사 결과를 확인하고, 오류가 있으면 400 Bad Request를 반환. 오류가 없으면 next()를 호출하여 다음 미들웨어 또는 라우터 로직으로 넘어감.

💫 channels.js validate 정리

alt text

  • validate 부분을 긍정으로 시작하도록 바꿈


코드 변경사항
유효성 검사 규칙 분리:
validateChannelId, validateUserId, validateChannelData, validateChannelName 등의 미들웨어로 유효성 검사 규칙을 분리. 이를 통해 재사용성을 높이고 코드를 더 간결하게 함.

validate 미들웨어:
유효성 검사를 통과했는지 확인하는 validate 미들웨어는 각 유효성 검사 규칙 뒤에 추가하여, 유효성 검사 실패 시 오류를 반환하고, 통과하면 다음 로직을 실행하도록 함.

라우터에서 미들웨어 적용:
각 라우트에서 필요한 유효성 검사를 미리 정의한 미들웨어 배열을 통해 적용.

🌊 users.js validate 추가 + 전체 테스트


<users.js 수정한 부분>
alt text


<실행결과>
alt text

  • 전체 테스트 결과 잘 됨!

🌊 로그인(인증) 세션- 인증과 인가

로그인(인증) 세션 : 사용자의 보안을 위해 세션의 만료 기간을 설정할 수 있음!

💫 인증(Authentication) = 로그인

나… 여기 가입된 유저임!!!!

ex)
쇼핑물 상품 볼 때? X(공개적인 데이터를 볼 때는 로그인 X)
쇼핑몰 장바구니 담을 때 O
쇼핑몰 상품 구매 O
마이 페이지 O.. 등등

💫 인가(Authorization)

허락을 해주는 것.
님 가입된 유저인 건 알겠는데 이 페이지에 들어올 수 있음?

ex)
같은 사이트 내에 관리자 / 고객에 따라 접근할 수 있는 페이지가 다름.
관리자든 고객이든 인증을 통해서 사이트에 가입된 사용자라는 걸 “증명”하는 것.
인증 후에, 이 친구 혹시 이 페이지 접근 권한이 있나?

🌊 쿠키와 세션 차이

✨쿠키🍪
1) 로그인 -> 서버가 쿠키를 구워줌🍪
2) 사용자 <-> 서버가 쿠키를 핑퐁

장점 : 서버가 저장 X => 서버 저장 공간 차지 X, Stateless =>RESTful
단점 : 보안 취약


✨세션: (로그인이 되어있는) 상태
1) 로그인 -> 서버가 금고를 만들어서 정보 저장, 그 금고 번호를 줌
2) 사용자 <-> 서버가 번호만 가지고 대화

장점 : 보안이 비교적 좋음.
단점 : 서버가 저장 O => 서버 저장 공간 차지 O, Stateless X

로그인(인증)을 매번 페이지 이동할 때마다 시키면? 화남.
그래서 사용하는 동안 유지가 됐으면 좋겠다 => 세션
쿠키의 단점을 해결하기 위해 나왔지만 사실상 쿠키와 장단점이 바뀜

✨JWT

  • 보안이 취약하다는 쿠키의 단점을 보완
  • 세션이 서버의 값, 상태를 저장한다는 Stateless X을 보완할 수 있음
  • 쿠키와 세션의 장단점을 보완해서 나옴

🌊 JWT 개념, 특징

💫 ✨JWT(JSON Web Token)

  • ✔개념 : JSON 형태의 데이터를 안전하게 전송하기 위한 (웹에서 사용하는) 토큰
    = 토큰을 가진 사용자가 “증명“을 하기 위한 수단

    cf. 토큰 : (인증용) 입장 가능한 유저임! / (인가용) 관리자 권한&일반 유저 권한

  • ✔장점

    • 보안에 강하다! <= 암호화가 되어 있음!
    • HTTP 특징을 잘 따랐음 = Stateless하다 <= “서버가 상태를 저장하지 않음”
    • 서버 부담을 줄임

      cf. 토큰을 발행하는 서버를 따로 만들 수 있음

🌊 JWT 구조 (feat. jwt.io)

💫 JWT 구조

jwt 공식사이트(jwt.io)
암호화된 토큰을 해석하기 위한 Debugger를 볼 수 있음!

헤더 : 토큰을 암호화 하는 데 사용한 알고리즘, 토큰의 형태(jwt)
페이로드 : 사용자 정보 (이름, 주소, 핸드폰, … 비밀번호 X)
서명 : 페이로드 값이 바뀌면, 서명값이 통째로 바뀌므로 JWT 믿고 사용가능


💫 복호화된 토큰의 뜻

HEADER:ALGORITHM & TOKEN TYPE(알고리즘과 토큰 형태를 알려줌)
JWT의 타입(typ)과 사용된 해싱 알고리즘(alg)에 대한 정보를 포함

{
  "alg": "HS256",
  "typ": "JWT"
}


PAYLOAD:DATA(정보를 담고 다님)
토큰에 포함될 실제 정보(클레임, Claim)를 담고 있습니다. 클레임은 보통 사용자 정보, 권한, 유효기간 등을 포함

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}


VERIFY SIGNATURE(서명 : 토큰을 보증함)
앞서 인코딩된 헤더와 페이로드를 결합한 후, 지정된 알고리즘(예: HMAC SHA256)으로 비밀 키를 이용해 서명한 값
서명은 토큰이 위변조되지 않았음을 보장하는 역할

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  your-256-bit-secret
)


eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

암호화된 JWT 토큰의 모습!
색깔의 순서대로 헤더, 페이로드, 서명!

🌊 JWT 인증/인가 절차

💫 JWT 인증/인가 절차

alt text

  1. 로그인 요청 :
    클라이언트는 사용자 이름과 비밀번호 같은 자격 증명을 서버에 전송.

  2. 서버의 자격 증명 검증 :
    서버는 클라이언트가 보낸 자격 증명이 올바른지 확인. 이 과정에서 데이터베이스를 참조하여 사용자가 입력한 정보가 맞는지 검증.

  3. JWT 토큰 발급 :
    자격 증명이 유효한 경우, 서버는 JWT 토큰을 생성하여 클라이언트에게 반환. 이 토큰에는 사용자 정보와 인증 관련 데이터가 포함.

  4. 클라이언트의 JWT 저장 :
    클라이언트는 받은 JWT 토큰을 브라우저의 로컬 스토리지나 쿠키에 저장.

  5. 추후 요청 시 토큰 전송 :
    이후 클라이언트가 서버에 요청을 보낼 때, HTTP 요청 헤더의 Authorization 필드에 JWT 토큰을 포함시켜 전송.

  6. 서버의 JWT 검증 :
    서버는 클라이언트로부터 받은 JWT 토큰을 검증. 여기서는 서명이 유효한지, 토큰이 만료되지 않았는지 등을 확인

  7. 요청 처리 및 응답 :
    JWT 토큰이 유효하면, 서버는 요청을 정상 처리하고 클라이언트에게 응답을 보냄. 반면, 토큰이 유효하지 않거나 만료된 경우에는 인증 실패 응답을 보냄.

🌊 JWT 구현

💫 JWT 구현

jsonwebtoken

npm install jsonwebtoken

<토큰 발급>

var jwt = require('jsonwebtoken'); // jwt 모듈 소환
// 서명 = 토큰 발행
var token = jwt.sign({ foo: 'bar' }, 'shhhhh');
// token 생성 = jwt 서명을 했다!! (페이로드, 나만의 암호키) + SHA256
console.log(token)

<복호화>

// 검증
// 만약 검증에 성공하면, 페이로드 값을 확인할 수 있음!
var decoded = jwt.verify(token, 'shhhhh');
console.log(decoded) // bar

alt text

  • iat : issued at(언제 발급되었는지!)

🌊 .env

💫 .env(environment : 환경 변수 ‘설정값’)

  • 개념 :
    • 개발을 하다가 포트넘버, 데이터베이스 계정, 암호키, … 등등 외부에 유출되면 안되는 중요한 환경 변수들을 따로 관리하기 위한 파일
      cf. 깃허브에 올라가면 안되는 값

파일 확장자 : .env

  • cf. txt, jpg, …


.env 파일 생성

npm install dotenv --save

.env 파일은 환경 변수 파일 => 프로젝트 폴더의 최상위에 위치

<.env파일에 JWT암호키 담기>
alt text

<jwt-demo.js 수정>
alt text

<express-demo.js 수정>
alt text

  • 포트넘버도 포함 가능

🌊 youtube에 jwt 적용

💫 youtube에 jwt 적용

alt text

  • POSTMAN에서 실행하면 잘 됨!

💫 cookie

cookie 파일 사용

npm install cookie-parser

<쿠키 적용>

res.cookie("token", token)

alt text

  • 쿠키에 암호값이 잘 넘어오는 걸 확인

💫 403

  • 클라이언트가 URL에 접근을 하는 데에 거절당했다는 뜻.
  • “나 너 인증 못해줘!!” 라는 것.

💫 cookie 설정 변경

alt text

Secure

  • HTTP
    http://localhost:1234/login

  • HTTPS(secure)
    인증서(암호화)로 감싸진 페이지라고 생각하면 됨!
    https://www.naver.com


httpOnly
= 프론트엔드가 아니라 API호출”만” 허락할 거임? : XSS 공격
(프론트엔드 공격 : 웹 브라우저 js 접근 => 공격)

  • true : 난 HTTP API로만 요청받을거임(그때만 쿠키접근o)
  • false : 프론트엔드에서 공격이 들어오면 쿠키도 공격받음
res.cookie("token", token, {
  httpOnly : true
})

alt text

  • 잘 적용된 걸 확인!

🌊 jwt 유효기간 설정

💫 jwt 유효기간 설정

보안을 위해 반드시 유효기간을 설정해줄 것!
영원히 유지되는 토큰을 맛보고싶은 게 아니라면…

const token = jwt.sign({
  email : user.email,
  name : user.name
}, process.env.PRIVATE_KEY, {
  expiresIn : '30m',
  issuer : "nanyoung"
});
  • 이렇게 하면 복호화했을 때 만료 시간과 작성자가 나옴



🌊 느낀 점(YWT)

Y 일을 통해 명확히 알게 되었거나 이해한 부분(한 일)에 대해 정리 :
인증과 인가, 쿠키&세션&JWT, JWT 구조와 인증/인가 절차

W 배운 점과 시사점 :
JWT 구조와 인증/인가 절차를 통해 로그인을 할 때 안전하게 전달할 수 있는 걸 배움!

T 응용하여 배운 것을 어디에 어떻게 적용할지:
혼자 로그인 홈페이지를 만들 때 활용할 수 있음!