인증 (Authentication) : ‘로그인’을 통해 서비스를 이용하는 것
회원가입, 로그인 등
서버 개발자가 인증에 대한 내용을 구현할 때에는 ‘Session’, ‘Cookie’, ‘JWT’에 대해 잘 알고 있어야 한다.
Session
서버에서 인증 데이터를 관리함
Session이 작동하는 방식
1. 사용자가 웹사이트에 접속합니다.
2. 그때 서버는 ‘session id’라는 고유 번호를 만들어요. 사용자 고유 번호표라고 생각하면 편해요.
3. 그리고 이 session id를 ‘쿠키’에 담아서 브라우저(클라이언트)에 보내요. (쿠키는 조금 뒤에 다시 볼게요.)
4. 브라우저는 이 session id를 내부 어딘가에 저장해요.
5. 이제 사용자가 서버에 무언가를 요청하면 자동으로 브라우저가 이 session id를 함께 서버에 보내요.
6. 서버는 함께 들어온 session id를 기반으로 누가 이 요청을 보낸 것인지 판단할 수 있는거죠.
예
import express from 'express';
import session from 'express-session';
const app = express();
// 세션 설정
app.use(session({
secret: '나만의 비밀키', // 암호화 키
resave: false, // 세션이 변경되지 않으면 저장 안 함
saveUninitialized: true // 초기화되지 않은 세션도 저장
}));
// 로그인
app.get('/login', (req, res) => {
req.session.user = { name: '곰돌이' }; // 세션에 사용자 정보 저장
console.log(`Session ID: ${req.sessionID}`);
res.send('로그인 완료! 안녕하세요, 곰돌이님!');
});
// 사용자가 로그인 상태인지 확인
app.get('/check', (req, res) => {
console.log(`Session ID: ${req.sessionID}`); // 현재 요청의 세션 ID 출력
if (req.session.user) {
res.send(`환영합니다, ${req.session.user.name}님!`);
} else {
res.send('로그인이 필요합니다!');
}
});
// 로그아웃
app.get('/logout', (req, res) => {
console.log(`Session ID (before destroy): ${req.sessionID}`); // 세션 삭제 전 ID 출력
req.session.destroy(() => { // 세션 삭제
res.send('로그아웃 완료!');
});
});
app.listen(3000, () => console.log('서버가 실행 중이에요!'));
브라우저와 논-브라우저
브라우저가 자동으로 쿠키를 보관해주는 것이기 때문에
브라우저가 아닌 곳(터미널에서)에서 로그인하면 쿠키가 저장안됨
터미널 예시
curl localhost:3000/login -v
쿠키
사용자 브라우저에 강제로 저장됨(보통 4Kb 이하의 아주 작은 데이터를 저장)
자동으로 번호표가 포함되어 요청함
사용자가 서버와 통신을 할 때 Cookie가 자동으로 서버에 전달되어요.
만료시간 지정 가능(만료 후 크키 사라짐. 재발급 받아야 함)
단점. 다른브라우저, 브라우저가 아닌 경우 사용하지 못함.
Cookie가 작동하는 방식
1. 사용자가 웹사이트에 접속합니다.
2. 서버가 사용자 브라우저에 저장하고 싶은 정보를 cookie로 만들어 브라우저에게 보냅니다.
3. 브라우저는 이 cookie를 저장합니다.(자동)
4. 사용자가 웹사이트에 다시 접속하면 브라우저가 자동으로 이 cookie를 서버에 보냅니다.
5. 서버는 이 cookie에 담겨있는 정보를 확인합니다.
import express from 'express';
import cookieParser from 'cookie-parser'; // 쿠키 파싱 미들웨어
const app = express();
// cookie-parser 미들웨어 등록
app.use(cookieParser());
// Cookie를 설정하는 예제
// 쿠키패서
app.get('/set-cookie', (req, res) => {
res.cookie('user', '곰돌이', { maxAge: 1000 * 60 * 60 }); // 1시간 동안 유지
res.send('Cookie가 설정되었습니다!');
});
// Cookie를 확인하는 예제
app.get('/get-cookie', (req, res) => {
console.log(req.cookie, req.cookies);
const userCookie = req.cookies['user'];
if (userCookie) {
res.send(`환영합니다, ${userCookie}님!`);
} else {
res.send('Cookie가 없네요.');
}
});
// Cookie를 삭제하는 예제
// 서버한테 지워달라 요청
app.get('/delete-cookie', (req, res) => {
res.clearCookie('user'); // Cookie 삭제
res.send('Cookie가 삭제되었습니다!');
});
app.listen(3000, () => console.log('서버가 실행 중입니다!'));
JWT !!!!!!! 중요!!!!!!!!!(쿠키도 중요)
JWT (JSON Web Token)
JWT는 인터넷에서 안전하게 데이터를 주고받기 위해 사용하는 토큰입니다.
토큰은 데이터가 암호화되어 포함된 일종의 “정보 덩어리”로 생각할 수 있어요.
주로 인증(로그인)과 권한 부여(Authorization)에 사용됩니다.
자체가 티켓
JWT는 디지털 티켓 같은 거예요.
이 입장권에는 크게 3가지 정보가 들어가있다고 볼 수 있어요.
이게 입장권이라는 정보 (입장권 종류)
유저에 대한 정보 (이름, 입장권 번호, 입장권 날짜 등)
위조 방지 QR (직원이 이 입장권이 진짜인지 확인하는 방법)
import express from 'express';
import jwt from 'jsonwebtoken';
const app = express();
const SECRET_KEY = 'mySecretKey'; // JWT 생성에 사용할 비밀 키
// 1. 로그인: JWT 생성
app.get('/login', (req, res) => {
const user = { id: 123, name: '곰돌이' }; // 사용자 정보
const token = jwt.sign( // jwt.sign : 이걸 jwt로 만들겠다
user,
SECRET_KEY,
{ expiresIn: '1h' } // 1시간 유효
);
res.json({ token }); // JWT를 브라우저에 전달
});
// 2. 인증된 사용자만 접근
app.get('/dashboard', (req, res) => {
const token = req.headers['authorization']; // 요청 헤더에서 JWT 가져옴
if (!token) return res.status(401).send('로그인이 필요합니다!');
jwt.verify(token, SECRET_KEY, (err, decoded) => {
if (err) return res.status(403).send('유효하지 않은 토큰입니다.');
res.send(`환영합니다, ${decoded.name}님!`);
});
});
app.listen(3000, () => console.log('서버 실행 중!'));
받은 jwt 읽기
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTIzLCJuYW1lIjoi6rOw64-M7J20IiwiaWF0IjoxNzM0MjcwMjY1LCJleHAiOjE3MzQyNzM4NjV9.-sbQOCTXmQ5lnQ3eXx07-dOJici5KO01_a4CX8Sc1wo
뭐하는 입장권이냐.나에대한 정보.유효한 입장권임.유효시간
읽기
HEADER:ALGORITHM & TOKEN TYPE
{
"alg": "HS256",
"typ": "JWT"
}
PAYLOAD:DATA
{
"id": 123,
"name": "곰돌이",
"iat": 1734270265,
"exp": 1734273865
}
VERIFY SIGNATURE
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
your-256-bit-secret
) secret base64 encoded
header, payload, signature
header- 토근 유형 알고리즘
payload - 내가 넣은 정보
signature - 헤더 페이로드를 결합 하고 비밀키를 사용하여 생성된 서명
실전
쿠키랑 같이 사용
JWT & Cookie:
유저가 서버에 어떤 정보를 요청합니다.
서버는 데이터베이스를 확인하고 해당 유저의 정보를 담은 JWT를 만듧니다.
그 JWT를 cookie로 만들어 브라우저에 저장합니다.
유저가 서버에 다시 요청을 보낼 때에 JWT가 Cookie에 담겨 서버로 전달됩니다.
서버는 JWT를 확인해보면 유저의 정보를 바로 알 수 있습니다.
JWT를 쿠키에 저장하고, 브라우저가 요청할 때 자동으로 쿠키를 서버로 보냄.
Cookie 없이 사용
JWT & Header:
유저가 서버에 어떤 정보를 요청합니다.
서버는 데이터베이스를 확인하고 해당 유저의 정보를 담은 JWT를 만듧니다.
그 JWT를 그대로 유저에게 전달합니다.
유저는 그 JWT를 request header에 담아 서버에 전달합니다.
서버는 JWT를 확인해보면 유저의 정보를 바로 알 수 있습니다.
JWT를 HTTP 헤더에 넣어서 서버로 전달.
주로 Authorization 헤더에 “Bearer [JWT]” 형식으로 보냄.
분반
헤더 토큰 사용 및 세션 관리: 관련사항 정리
1. 토큰 관리 및 인증 흐름
- 모바일 등 클라이언트는 요청 시 토큰을 헤더에 포함하여 인증.
- 레디스는 세션 관리 도구로 사용되며, 토큰을 저장하고 만료 시간까지 유효성을 보장.
- 로그아웃 처리:
- 로그아웃 요청이 오면, 레디스에서 해당 토큰을 삭제하여 세션 무효화.
- 단일 토큰 사용:
- Access Token, Refresh Token을 나누지 않고, 하나의 토큰으로 모든 처리를 통합.
2. 레디스와 세션 정보 관리
- 레디스 역할:
- 세션 데이터 저장: 유저 정보를 캐싱하여 빠른 인증 및 상태 확인 가능.
- 입장 상태 등 특정 정보 관리 가능.
- 입장 상태 관리:
- 사용자가 "입장했다"는 정보를 세션(또는 레디스)에 저장하여 추적 가능.
- 로그아웃 시 세션 초기화:
- 로그아웃 요청 시 레디스의 해당 데이터 삭제.
3. JWT 대체 및 설계 간소화
- JWT를 사용할 수 있으나 현재 설계에서는 필요하지 않음.
- 이유: 레디스를 활용해 유저 정보를 효율적으로 관리 가능.
- 토큰 검증 및 상태 추적이 레디스를 통해 처리되므로 JWT의 장점(서버리스 인증)을 활용할 필요가 적음.
4. 로그아웃 여부에 따른 관리 방식
- 로그아웃이 있는 경우:
- 사용자가 명시적으로 로그아웃을 요청하면, 레디스에서 세션 삭제.
- 즉, 해당 사용자의 인증 정보가 무효화됨.
- 로그아웃이 없는 경우:
- Access Token, Refresh Token 구조를 통해 자동 만료 또는 갱신으로 세션 관리 가능.
설계의 주요 포인트
- 레디스 기반 단일 토큰 관리: 단일 토큰으로 인증, 상태 추적, 로그아웃 처리 모두 가능.
- 간단하고 확장 가능한 구조: JWT 없이도 레디스를 통해 유저 정보와 상태를 효과적으로 관리.
- 상태 추적: 입장 여부 등 사용자 상태를 세션 데이터에 포함하여 필요 시 참조 가능.
시크릿키는 .env에 있어야함
숙제
숙제하기
'내일배움캠프_게임서버(202410) > 분반 수업 Basic-A' 카테고리의 다른 글
교육과정 틀기 (0) | 2024.12.19 |
---|---|
베이직 강의 24.12.12 - 5주차 Database와 ORM(Prisma) (1) | 2024.12.12 |
basic 4주차 과제 (3) | 2024.12.07 |
4주차 Express, Restful API - 숙제중 (2) | 2024.12.05 |
베이직 241203 화 - 숙제 해설 (0) | 2024.12.03 |