티스토리 뷰
교육을 들을 수 있는 기회가 생겼다..!!
현재 진행중인 프로젝트에서 관리하고 있는 방법과 배우고 나서 어떻게 관리하면 좋을지 비교하고 수정하기 위해 작성해보겠다😆
진행중인 프로젝트에서 관리하고 있는 방법을 작성한 블로그
1. https://anywhereim.tistory.com/95
2. https://anywhereim.tistory.com/111
3. https://anywhereim.tistory.com/112
인가: 권한이 있는지 없는지 여부를 판단
인증: 로그인을 하는 행위
개념정리
` accessToken `
목적:
1. accessToken은 사용자가 서버에 로그인 후 서비스를 이용할 수 있는 권한이 있는지 여부를 판단하는데 사용된다.
2. 서버에서는 서버에서 발급한 accessToken이 맞는지 확인 후 인가를 부여
3. accessToken 만료시간 측정
유효기간:
1. 보안을 강화하기 위해 accessToken의 유효기간은 몇분에서 몇 시간으로 짧게 유지
보안성:
1. accessToken이 노출되더라도 유효기간이 짧기 때문에 refreshToken 보다 보안 위협이 상대적으로 낮다.
`refreshToken`
목적:
1. refreshToken은 accessToken의 유효기간이 만료된 후 새로운 accessToken을 발급받기 위해 사용
2. accessToken 만료시간이 지나더라도 재발급을 통해 재로그인을 하지 않도록 함
유효기간:
1. accessToken에 비해 긴 시간동안 유효하다.
보안성:
1. refreshToken이 유출될 경우 사용자의 권한을 오랫동안 남용할 수 있게되므로 높은 보안을 필요로 한다.
상단에 현재 사용중인 관리 방법을 작성한 블로그 경로를 걸어두었는데
내가 작성한 코드가 관리 방법인지에 대한 의문이 들었다.
그래서 한번에 볼 수 있도록 글로써 작성해보고자 한다.
작동 방식과 함께 관리 방법을 함께 풀어보자( 이 관리 방법)
작동 방식과 관리 방법
1. 사용자가 로그인 요청 시 응답값으로 accessToken과 헤더에 refreshToken이 담긴 쿠키를 담아서 받는다.
2. 이때 로그인 요청과 동시에 응답값으로 받은
- accessToken을 "token" 이라는 이름으로 localstorage에 담고
- 디코딩 후 디코딩된 값을 "user"라는 이름으로 zustand parsist를 이용해 localstorage에 담는다.
"
❓localstorage를 선택한 이유
- 브라우저 창이 닫힐 경우 삭제
- 백앤드에서 header에 직접적으로 token을 담아서 보낼 것을 요구
❓ 그렇다면 여기에서 백앤드는 왜 header에 직접적으로 token을 담아서 보낼 것을 요구하였는가
⭐`Bearer` token 정책⭐
OAuth2.0 인증 프레임워크에서 사용되는 방식으로 accessToken을 Http 요청의 `Authorzation` 헤더에
`Bearer` 이라는 타입으로 포함시켜 서버에 전송하는 것을 의미한다.
이 방식은 accessToken을 사용해 api 요청이 이증되는 방식이다.
- 보안성:
accessToken이 직접 헤더에 포함되어 있어 cookie를 사용하는 것에 비해 특정 도메인에 종속되지 않고,
cookie를 통한 cross-site request forgery 공격에 덜 취약하다.
- 명확성과 간단함:
클라이언트는 token을 헤더에 명확하게 포함시켜 요청을 보내므로 서버는 요청을 받알쓸때 헤더에서 바로 token을 읽어 인증을 처리할 수 있다.
"
3. 3개의 axiosInstance를 만들어 api를 요청
✅refreshToken 요구
- accessToken을 재발급 받기 위한 개별 axiosInstance (axios.defaults.withCredentials = true)
✅ accessToken 요구
- accessToke을 필요로 하는 경우 header에 accesstoken을 필요로 하는 api를 요청하는 axiosInstace
✅ 요구 사항 없음
- accessToken을 필요로 하지 않는 api를 요청하는 경우 axiosInstace (axios.defaults.withCredentials = false)
< refreshToken 요구 > accessToken 재발급
import { decodeTokenOnServer } from "./decode/decodedAxios";
import { requests } from "./request";
import axios from "axios";
axios.defaults.withCredentials = true;
const axiosInstance = axios.create({
baseURL: process.env.NEXT_PUBLIC_BASE_URL,
headers: {
"Content-Type": "application/json",
},
responseType: "json",
withCredentials: true,
});
export const getNewAccessToken = async () => {
try {
const response = await axiosInstance.post(
`${requests.getNewAccessToken}`,
{},
{
withCredentials: true,
}
);
const newAccessToken = response.data.data.accessToken;
await decodeTokenOnServer(newAccessToken);
localStorage.setItem("token", newAccessToken);
return newAccessToken;
} catch (error: any) {
alert("로그인 정보가 만료되어 로그인이 필요합니다.");
localStorage.removeItem("token");
localStorage.removeItem("user");
window.location.href = "/users/login";
return null;
}
};
- cookie에 있는 refreshToken을 함께 전달.
- 재발급 받은 accessToken을 디코딩 하는 함수에 전달
- refreshToken 만료로 인해 error를 반환 받는 경우 localStorage에 저장된 값 삭제 및 로그인 페이지로 리다이렉트
- 로그인 api 요청 시 instance는 꼭 withCreadential: ture 설정이 되어있는 axios instance를 사용해주어야한다! 그래야 header로 받은 쿠키가 저장이 된다.
< accessToken 요구 > header에 token 설정
import axios from "axios";
import { getNewAccessToken } from "./withCredentials";
const axiosInstance = axios.create({
baseURL: process.env.NEXT_PUBLIC_BASE_URL,
headers: {
"Content-Type": "application/json",
},
responseType: "json",
withCredentials: false,
});
// 요청 인터셉터 설정
axiosInstance.interceptors.request.use(
(config) => {
const token = localStorage.getItem("token");
if (token) {
config.headers["Authorization"] = `Bearer ${token}`;
}
return config;
},
(error) => {
return Promise.reject(error.message);
}
);
// 응답 인터셉터 설정
axiosInstance.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;
//중복 요청 방지
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
const newAccessToken = await getNewAccessToken();
if (newAccessToken) {
// 원래 요청의 헤더를 새로운 토큰으로 업데이트
originalRequest.headers["Authorization"] = `Bearer ${newAccessToken}`;
return axiosInstance(originalRequest);
}
}
return Promise.reject(error);
}
);
export default axiosInstance;
- api 요청 시 accessToken으로 가지고 api 요청
- accessToken 만료로 인해 error 발생 시 `getNewAccessToken` 를 호출
- accessToken 재발급 성공 시 api 재요청
< 요구사항 없음 >
import axios from "axios";
const basicAxiosInstance = axios.create({
baseURL: process.env.NEXT_PUBLIC_BASE_URL,
headers: {
"Content-Type": "application/json",
},
responseType: "json",
withCredentials: false,
});
export default basicAxiosInstance;
- 인가가 필요 없는 api 요청 시 사용
4. token 만료처리
api요청이 필요한 페이지로 넘어가는 버튼을 클릭할 때 refreshToken 만료를 확인하여 api요청 시 로그인페이지로 리다이렉트 되는 경우를 방지
** api 요청이 필요한 페이지로 넘어가는 버튼은 user의 정보가 있는 경우에만 보임
import { getNewAccessToken } from "@/app/api/withCredentials";
const timeStamp = () => {
const getLoginUserInfo = localStorage.getItem("user");
if (getLoginUserInfo) {
const userObj = JSON.parse(getLoginUserInfo);
const expValue = userObj.state.user.exp * 1000;
const nowTime = new Date().getTime();
return nowTime > expValue;
} else{
}
return false;
};
export const expirationTime = async () => {
if (timeStamp()) {
await getNewAccessToken();
}
};
'TIL' 카테고리의 다른 글
Supabase와 Prisma 함께 사용하기 2. migrations (0) | 2024.07.17 |
---|---|
Supabase와 Prisma 함께 사용하기 1.셋팅 (0) | 2024.07.16 |
axiosInstance 리펙토링하기 (0) | 2024.07.06 |
토큰 만료처리하기 (0) | 2024.07.06 |
react-hook-form 나홀로 정리하기 (0) | 2024.07.02 |
- Total
- Today
- Yesterday
- readme작성해보기
- styled component 조건부 사용방법
- Warning: A component is changing an uncontrolled input to be controlled.
- 영화별점만들기
- axios 사용하기
- 별점만들기
- 유효성검사
- styled component GlobalStyle 사용방법
- readme 이미지 추가 방법
- 에러모음집
- readme 작성 방법
- axios CRUD
- nextjs 토큰 만료처리하기
- Fetch와 Axios 의 장단점
- 영화 별점
- Warning: Each child in a list should have a unique "key" prop.
- simple Icon 사용방법
- 별점 색채우기
- styled component 설치방법
- git cache
- axios instance 작성하기
- axios 설치하기
- styled component 사용방법
- Warning: validateDOMNesting(...): <li> cannot appear as a descendant of <li>
- readme 역할
- 유효성검사 css
- readme 작성해야 하는 이유
- axiosinstance 사용 시 토큰 사용 법
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |