iT邦幫忙

2025 iThome 鐵人賽

DAY 13
0
Modern Web

Modern Web:從基礎、框架到前端學習系列 第 23

Day 23:Token 自動刷新與狀態維護

  • 分享至 

  • xImage
  •  

學習目標

  1. 了解Access TokenRefresh Token的概念與差異。
  2. 實作自動刷新 Token 的流程。
  3. 讓登入狀態在 Token 過期後仍可自動延長。
  4. 建立簡易會員系統架構:登入 → 存 Token → 自動刷新 → 登出。

理論講解

1.兩種 Token 的角色

類型->功能->有效時間->儲存位置
Access Token->每次呼叫 API 時使用的臨時身分證->約 15 分鐘->localStorage 或記憶體
Refresh Token->用來更新 Access Token 的憑證->可達數小時或數天->安全地存在後端或 httpOnly cookie


2.Token 更新流程(簡化版)

  1. 使用者登入 → 後端回傳access_tokenrefresh_token
  2. 前端在每次 API 呼叫時使用access_token
  3. access_token過期時,後端回傳401 Unauthorized
  4. 前端自動用refresh_token向後端換新 Token
  5. 更新成功後繼續原本的請求

實作:自動刷新 Token 模擬系統

專案結構

token-refresh-demo/
 ├── index.html
 ├── style.css
 └── app.js

index.html

<!DOCTYPE html>
<html lang="zh-Hant">
<head>
  <meta charset="UTF-8">
  <title>Token 自動刷新 Demo</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <h1>🔐 Token 自動刷新示範</h1>

  <button id="loginBtn">登入取得 Token</button>
  <button id="apiBtn" disabled>呼叫受保護 API</button>
  <button id="logoutBtn" disabled>登出</button>

  <div id="output"></div>

  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
  <script src="app.js"></script>
</body>
</html>

style.css

body {
  font-family: Arial, sans-serif;
  text-align: center;
  margin-top: 60px;
}
button {
  padding: 10px 15px;
  margin: 5px;
  cursor: pointer;
}
#output {
  margin-top: 20px;
  padding: 15px;
  border: 1px solid #ddd;
  width: 60%;
  margin-left: auto;
  margin-right: auto;
  border-radius: 8px;
  background-color: #f9f9f9;
}

app.js

const output = document.getElementById('output');
const loginBtn = document.getElementById('loginBtn');
const apiBtn = document.getElementById('apiBtn');
const logoutBtn = document.getElementById('logoutBtn');

// 模擬 Token 儲存
let accessToken = null;
let refreshToken = null;
let tokenExpireTime = null;

// 模擬登入取得 Token
loginBtn.addEventListener('click', async () => {
  // 模擬登入成功
  accessToken = "ACCESS_" + Math.random().toString(36).substr(2);
  refreshToken = "REFRESH_" + Math.random().toString(36).substr(2);
  tokenExpireTime = Date.now() + 10000; // Token 10 秒過期

  output.innerHTML = `
    <p>登入成功 🎉</p>
    <p>Access Token: ${accessToken}</p>
    <p>有效期限:10 秒</p>
  `;
  apiBtn.disabled = false;
  logoutBtn.disabled = false;
});

// 模擬呼叫受保護 API
apiBtn.addEventListener('click', async () => {
  if (Date.now() > tokenExpireTime) {
    output.innerHTML += `<p>⚠️ Access Token 已過期,嘗試刷新中...</p>`;
    await refreshAccessToken();
  }

  // 模擬 API 呼叫
  output.innerHTML += `<p>✅ 使用 Token 成功呼叫 API (${new Date().toLocaleTimeString()})</p>`;
});

// 模擬刷新 Token
async function refreshAccessToken() {
  return new Promise((resolve) => {
    setTimeout(() => {
      accessToken = "ACCESS_" + Math.random().toString(36).substr(2);
      tokenExpireTime = Date.now() + 10000; // 新的 Token 再延長 10 秒
      output.innerHTML += `<p>🔁 Token 已刷新成功:${accessToken}</p>`;
      resolve();
    }, 1500);
  });
}

// 登出
logoutBtn.addEventListener('click', () => {
  accessToken = null;
  refreshToken = null;
  tokenExpireTime = null;
  output.innerHTML = `<p>已登出。</p>`;
  apiBtn.disabled = true;
  logoutBtn.disabled = true;
});

今日成果

  • 了解Access Token / Refresh Token 的區別與流程
  • 實作了自動刷新 Token 的模擬系統
  • 學會如何在 Token 過期時自動更新並繼續執行請求
  • 建立前端登入狀態維護的基礎概念

延伸挑戰

  1. 改成實際使用 API(例如 Firebase Auth)。
  2. axios攔截器(interceptor)自動檢查 Token 是否過期。
  3. 在 Token 即將過期前(例如剩 2 分鐘)主動刷新。

上一篇
Day 22:受保護 API 與 Token 驗證流程
下一篇
Day 24 - LocalStorage 進階應用與資料持久化實作
系列文
Modern Web:從基礎、框架到前端學習24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言