還記得我們在[Day11] 登入、註冊API開發和HTTP Authentication(JWT)有介紹過整個登入到授權的流程。
先前已經開發完登入的功能,當呼叫login api成功後,會收到使用者的資訊。
在開發儲存前,先簡單說一下我們要把JWT存放在哪個web storage(cookie、localstorage、sessionstorage)裡。
考慮到安全性會建議存放在
Cookie
內(因為Cookie可以控制過期時間),詳情請見Token 放 localStorage?sessionStorage?還是 Cookie?
但由於這裡想快速實作出功能,所以先存放至localstorage
中。
在把JWT
儲存到localstorage
裡前,因為回傳的是一個JSON,Web Storage 只能儲存字串,所以要透過JSON.stringfy來轉換。
回傳資料:
{
"token": 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
"id": '6512e8482186f21378ab5d34'
}
//Login.js
const handleSubmit = (event) => {
if (!formIsValid) return;
event.preventDefault();
const userData = {
email,
password,
};
api
.post("/auth/login", userData)
.then((result) => {
//將回傳的token存放到localstorage
localStorage.setItem("user", JSON.stringify(result));
})
.catch((error) => {
setErrorMsg('Login failed. Your email or password is incorrect.')
console.error(error);
});
};
當我們完成登入後就能在localstorage裡面看到儲存的使用者資訊了
當使用者想要訪問一個受到保護的資源(例如API端點)時,他們必須在其請求中帶上JWT,通常是放在HTTP的Authorization標頭中。
我們要在每次呼叫API時在Authorization header都加上JWT,讓後端確認是不是有被授權存取資料。
回到api.js
,加上攔截器axios的interceptor
//api.js
import axios from 'axios';
const api = axios.create({
baseURL: 'http://localhost:5200/api',
});
//因為登入和註冊路由不需要攜帶jwt,所以將他們排除
const EXCLUDED_URLS = ['/auth/login', '/auth/register'];
// 使用request攔截器(interceptor)為每個request 加上 token
api.interceptors.request.use((config) => {
if (!EXCLUDED_URLS.includes(config.url)) {
// 從 localStorage 中獲取使用者資訊
const user = JSON.parse(localStorage.getItem('user'));
// 使用 && 運算符,檢查 user 和 user.data 是否存在
const token = user && user.data && user.data.token;
// 如果 token 存在,
// 則將他加到到request header的 Authorization 屬性中
if (token) {
config.headers['Authorization'] = 'Bearer ' + token;
}
}
// 回傳更新後的配置
return config;
}, (error) => {
return Promise.reject(error);
});
export default api;
經過這樣處理後,當我們之後呼叫api時就能自動帶上JWT了。
本次程式碼我放在這github