-
[인증/보안] TokencodeStates front-end/node(server) 2023. 3. 8. 21:09반응형
목차
📌 Token
📍 해싱(Hashing)
hash : 고기, 감자, 야채 등을 잘게 다져서 볶아낸 음식
암호화 방식 중 하나
해싱은 암호화만 가능하다, 복호화 불가능
🔗 해시 함수(Hash Function)
임의의 값을 넣으면 일정한 크기의 결과 값이 나온다
- 항상 같은 길이의 문자열을 리턴
- 서로 다른 문자열에 동일한 해시 함수를 사용하면 반드시 다른 결과값이 나온다.
- 동일한 문자열에 동일한 해시 함수를 사용하면 항상 같은 결과값이 나온다.
🤦♂️뭔소리노
예시를 확인해봤다.
어떠한 값을 넣어도 결과 값을 암호화하면서
다시 암호화한 값으로 임의의 값을 유추 가능하다.
input : higgs output : 3FD838397804752452BAC4F637BBE6D8 input : 동해물과백두산이마르고닳도록하느님이보우하사우리나라만세무궁화삼천리화려강산대한사람대한으로길이보전하세남산위에저소나무철갑을두른듯바람서리불변함은우리기상일세무궁화삼천리화려강산대한사람대한으로길이보전하세 output : A98DF759C9243759B126FF035BDF4D75
🔗 레인보우 테이블과 솔트(Salt)
레인보우 테이블
결과값이 나온다는 특성을 통해 해시 함수를 거치기 이전의 값을 알아낼 수 있도록 기록해놓은 표
솔트
이전의 값을 알아낼 수 있다는 보안상 위협으로 인해 소금을 치듯 이전의 값을 어렵게 만드는 방법이다.
📍 Token
사용자 인증 정보와 권한 정보를 포함한 정보를 담은 암호화된 문자열
'토큰'을 클라이언트에게 부여하다. 이 토큰은 유일하다
🔗 토큰 인증 방식
- POST/login 클라이언트는 로그인 요청
- 서버는 인증 정보 검증
- 유효하다면 해당 유저에 대한 토큰을 생성
- 클라이언트에서 토큰 전달
- 클라이언트에 토큰 저장
- GET/someinfo 요청과 함께 토큰 전달
- 서버는 유효한 토큰인지 검증
- 유효하다면 요청에 대한 응답 데이터 전송
🔗 토큰 인증 방식 장/단점
장점 : 무상태성, 확장성, 어디서나 토큰 생성 가능, 권한 부여에 용이
단점 : 토큰 탈취의 문제 👉 무상태성, 유효기간, 토큰의 크기
🔗 토큰 인증 방식 문제의 해결 방안
엑세스 토큰(Access Token)
사용자가 서버 리소스에 접근할 수 있도록 접근 권한을 제공하는 토큰
보안을 위해 만료 주기가 짧게 설정되어 있다.
리프레시 토큰(Refresh Token)
토큰의 짧은 만료 주기로 인해 발생되는 사용자 경험 하락을 막기 위해 고안된 토큰
기존에 발급받은 액세스 토큰이 만료되었을 때 새로운 엑세스 토큰을 얻기위해 사용함
🔑 Access Token 유효 시 동작 흐름
- POST/login 클라이언트는 로그인 요청
- 서버는 인증 정보 검증
- 유효하다면 해당 유저에 대한 토큰을 생성(액세스, 리프레시 토큰 둘다 생성)
- 클라이언트에서 토큰 전달(토큰 둘 다 전달)
- 클라이언트에 토큰 저장(토큰 둘 다 저장)
- GET/someinfo 요청과 함께 토큰 전달(액세스 토큰 전달)
- 서버는 유효한 토큰인지 검증(액세스 토큰 검증)
- 유효하다면 요청에 대한 응답 데이터 전송
🔑 Access Token 만료 시 동작 흐름
- 클라이언트는 GET/someInfo 요청과 함께 엑세스 토큰 전달
- 서버는 엑세스 토큰 검증
- 서버는 Error : Token Expired 만료된 액세스 토큰에 대한 응답 전송
- 클라이언트는 POST/auth/refresh_token 새로운 액세스 토큰 발급 요청 (+리프레시 토큰)
- 서버는 리프레시 토큰 검증
- 서버는 새로운 액세스 토큰 생성
- 서버는 새로운 엑세스 토큰 응답으로 전송
- 클라이언트는 재로그인 없이 지속된 인증 상태를 확인할 수 있다.
🔗 JWT
JSON Web Token
데이터 전송에 사용하는 토큰 기방 인증 기술로 JSON 형식으로 저장한 정보(payload)를 암호화하여 전송
🔗 쿠키 vs 세션 vs 토큰
🔗 [실습] JWT 토큰을 활용하여 로그인 상태 유지
로직은 cookie와 동일하니 먼저 보고오기
[인증/보안] Cookie
HTML 삽입 미리보기할 수 없는 소스 📌 Cookie 📍 Cookie 서버에서 클라이언트에 영속성있는 데이터를 저장하는 방법 서버는 클라이언트의 쿠키를 이용하여 데이터를 가져올 수 있다 http 프로토콜
hwantech.tistory.com
1.env.example 환경변수 설정
본인이 원하는 환경 변수 지정 후 .env.examle -> .env 로 변경
ACCESS_SECRET= REFRESH_SECRET=
2. server 코드 작성
server/controllers/users/userInfo.js
const { USER_DATA } = require('../../db/data'); const { verifyToken, generateToken } = require('../helper/tokenFunctions'); module.exports = async (req, res) => { const accessToken = req.cookies['access_jwt']; const refreshToken = req.cookies['refresh_jwt']; const accessPayload = verifyToken('access', accessToken); if (accessPayload) { const userInfo = { ...USER_DATA.filter((user) => user.id === accessPayload.id)[0] }; if (!userInfo) { return res.status(401).send('Not Authorized'); } delete userInfo.password; return res.json(userInfo); } else if (refreshToken) { const refreshPayload = verifyToken('refresh', refreshToken); if (!refreshPayload) { return res.status(401).send('Not Authorized'); } const userInfo = USER_DATA.filter((user) => user.id === refreshPayload.id)[0]; const { accessToken } = generateToken(userInfo); res.cookie('access_jwt', accessToken, { domain: 'localhost', path: '/', sameSite: 'none', httpOnly: true, secure: true, // Expires 옵션이 없는 Session Cookie }); return res.json({ ...userInfo, password: undefined }); } return res.status(401).send('Not Authorized'); };
server/controllers/users/login.js
const { USER_DATA } = require('../../db/data'); const { generateToken } = require('../helper/tokenFunctions'); module.exports = async (req, res) => { const { userId, password } = req.body.loginInfo; const { checkedKeepLogin } = req.body; const userInfo = { ...USER_DATA.filter((user) => user.userId === userId && user.password === password)[0], }; if (!userInfo.id) { res.status(401).send('Not Authorized'); } const { accessToken, refreshToken } = generateToken(userInfo, checkedKeepLogin); if (refreshToken) { res.cookie('refresh_jwt', refreshToken, { domain: 'localhost', path: '/', sameSite: 'none', httpOnly: true, secure: true, expires: new Date(Date.now() + 24 * 3600 * 1000 * 7), // 7일 후 소멸되는 Persistent Cookie }); } res.cookie('access_jwt', accessToken, { domain: 'localhost', path: '/', sameSite: 'none', httpOnly: true, secure: true, // Expires 옵션이 없는 Session Cookie }); return res.redirect('/userinfo'); };
server/controllers/users/logout.js
module.exports = (req, res) => { const refreshToken = req.cookies['refresh_jwt']; if (refreshToken) { res.clearCookie('refresh_jwt', { domain: 'localhost', path: '/', sameSite: 'none', secure: true, }); } res.clearCookie('access_jwt', { domain: 'localhost', path: '/', sameSite: 'none', secure: true, }); return res.status(205).send('Logged Out Successfully'); };
3. 확인해보기
Error!!!!!??????
get요청부터 들어갔는지 볼려고 콘솔로그 쳐봤더니 에러뜬다;;;; 뭐지뭐지
내가 소스를 잘못 작성한지 알고 2시간 내내 소스만 봤다;;;; 바보같이
구글링할껄;;;;
해결방안
Express (Node.js) http error
프론트 엔드와 백 엔드를 각각 개발할 때ex)프론트 엔드 : localhost:3000백 엔드 : localhost:3001프론트엔드에서 localhost:3001 express로 서버를 열 때에러 발생시백 엔드 API 호출 URL을 아래와 같이https://
velog.io
보고 해결했다 문제는 https -> http로 변경하는 것
바꿨더니 된다;;;;;;
왜 이게 안되는지는 아직도 몰겠다; 아시는 분 댓글점여 😥😥😥
반응형'codeStates front-end > node(server)' 카테고리의 다른 글
아마존 웹 서비스(AWS) (0) 2023.03.31 [인증/보안] OAuth (0) 2023.03.09 [인증/보안] Session (0) 2023.03.08 [인증/보안] Cookie (0) 2023.03.07 [네트워크] 심화, TCP/IP, 네트워크 계층 모델, OSI 7계층 모델, ... (0) 2023.03.06