앞에서 간단하게 로그인해서 access token을 받아오고 받아온 access token을 request header에 저장하는것 까지
공부를 했다.
이제 access token의 갱신을 어떻게 하는지에 대해 공부하자.
먼저 App.jsx 파일을 수정하자. App.jsx 가 최초 render 될 떄 refresh token을 체크하고 access token을 갱신하도록했는데. 이부분을 utils.js 파일로 옴기도록 하자 이유는 이 refresh token 하는 부분을 로그인 할떄도 사용하기 위해서이다.
로그인을 한 후에도 주기적으로 access token이 갱신되어야 하므로...
// App.jsx
import './App.css';
import { BrowserRouter, Route } from 'react-router-dom';
import LoginPage from './pages/LoginPage';
import HomePage from './pages/HomePage';
import AuthRoute from './component/AuthRoute';
import Counnter from './component/Counter';
import { useEffect, useState } from 'react';
import { refreshToken } from './utils';
function App() {
const [isLogin , setIsLogin] = useState(false);
const [loading , setLoading] = useState(false);
useEffect(()=>{
try{
refreshToken(loginCallBack);
}catch(e){
console.log(e);
}
},[]);
function loginCallBack(login){
setIsLogin(login);
setLoading(true);
}
if(loading){
return (
<div className="App">
<BrowserRouter>
<AuthRoute exact isLogin={isLogin} path="/" component={HomePage} />
<Route path="/login" render={(props)=> <LoginPage {...props} loginCallBack={loginCallBack}/>} />
<AuthRoute path="/counter" isLogin={isLogin} component={Counnter} />
</BrowserRouter>
</div>
);
}else{
return (
<div>
Loading ....
</div>
)
}
}
export default App;
//utils.js
import axios from 'axios';
export const refreshToken = function(callback){
axios.post("/auth/refreshToken" , {
headers: {
"Content-Type": 'application/json',
}})
.then(res =>{
console.log("res.data.accessToken : " + res.data);
axios.defaults.headers.common['Authorization'] = 'Bearer ' + res.data;
if(callback){
callback(true);
}
setTimeout(function(){
refreshToken(null) ;
}, (60 * 1000));
})
.catch(ex=>{
console.log("app silent requset fail : " + ex);
if(callback){
callback(false);
}
})
.finally(()=>{
console.log("refresh token request end");
// setLoading(true);
});
};
이부분을 추가 하면 이제 silent 로그인시에 자동으로 access token을 갱신하게 된다. 이유는 setTimeout 부분을 추가했기 때문이다.
이제 로그인부분도 수정해보자.
import { useEffect } from "react";
import axios from "axios";
import { refreshToken } from './../utils';
function LoginPage(props){
function joinHandler(){
try{
let data = {email: "devracoon@naver.com"};
axios.post("/auth/login" ,JSON.stringify(data), {
headers: {
"Content-Type": 'application/json',
}})
.then(res =>{
console.log("res.data.accessToken : " + res.data);
axios.defaults.headers.common['Authorization'] = 'Bearer ' + res.data;
props.loginCallBack(true);
props.history.push("/");
//이부분 추가함 60초 뒤에 refresh token이 실행되도록 수정.
//이후 refresh token에서 자동으로 setTimeout이 발생해 주기적으로 access Token이 갱신됨
setTimeout(function(){
refreshToken(null);
} , 60 * 1000);
})
.catch(ex=>{
console.log("login requset fail : " + ex);
})
.finally(()=>{console.log("login request end")});
}catch(e){
console.log(e);
}
}
useEffect(()=>{
console.log("LoginPage render ... ");
})
return(
<div>
<span>Login Page</span>
<button type="button" onClick={joinHandler}>Join</button>
</div>
)
}
export default LoginPage;
이렇게 처리를 하고 나면 access token의 갱신은 자동으로 이뤄지게 된다.
그러면 refresh token이 만료되었을때는 다시 로그인을 해야 하는데 그럴때 마다 axios request 보낼때 체크를 하나하나 다 해야 하나? 아니다. axios에서도 interceptor가 존재한다.
axios interceptor를 index.js 파일에 추가하자.
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import axios from 'axios';
axios.interceptors.response.use(
function (response) {
/*
http status가 200인 경우
응답 성공 직전 호출됩니다.
.then() 으로 이어집니다.
*/
return response;
},
function (error) {
/*
http status가 200이 아닌 경우
응답 에러 직전 호출됩니다.
.catch() 으로 이어집니다.
*/
//401은 Access Token or Refresh Token 이 invalid 될때
//response data의 code값이
// 4401 : access Token error , 4402: refresh Token error
if(error.response.status === 401){
if(error.response.data.code === '4401'){
window.location.href= '/';
}
}
return Promise.reject(error);
}
);
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
이렇게 하고나면 token 처리에 대한 부분은 끝난다. 이제 본격적으로 UI 개발을 시작해보자 .
UI는 material ui template를 이용해서 좀 더 쉽게 개발하려고 한다.
'React를 시작해보자' 카테고리의 다른 글
8) React - Material UI를 이용한 UI 만들기 -1부 (0) | 2020.12.01 |
---|---|
6) React - JWT를 이용한 로그인 인증 - 2부 (0) | 2020.11.23 |
5) React - JWT를 이용한 로그인 인증 - 1부 (8) | 2020.11.22 |
4) React - Route를 이용해서 메뉴를 만들어보자. (0) | 2020.11.11 |
3) React - 간단한 Counter UI를 만들어보자. (0) | 2020.11.10 |