# Storage, JWT, Cookie, Restful # 儲存方式比較 | 特性/儲存方式 | Cookie | Local Storage | Session Storage | | -------------- | ------------------------- | ----------------------- | --------------------- | | 定義 | 伺服器儲存在瀏覽器的<br>小型資料片段 | 瀏覽器中的 Web Storage API 的一部分 | 瀏覽器中的 Web Storage API 的一部分 | | 大小限制 | 約 4KB | 約 5~10 MB | 約 5~10 MB | | 壽命 | 可設定過期時間 | <b>永久儲存</b><br>除非手動刪除 | 瀏覽器會話結束時消失 | | 安全性 | 可設定 `Secure` 和 `HttpOnly` 旗標 | 相對較低 | 相對較低 | | 跨域 | 僅對建立該 `Cookie` 的域名有效 | 僅在相同的域名下可用 | 僅在相同的域名下可用 | | 每次請求附帶 | 是 | 否 | 否 | | 主要用途 | 會話管理、使用者追蹤 | 儲存大量資料、使用者偏好 | 單次瀏覽會話的資料儲存 | ## 場景 | 特性/技術 | JWT | Cookie | 後端 Session | | --------------- | ------------------------------- | ----------------------------- | ---------------------------- | | 優點 | 無狀態、跨域、靈活性、前後端分離 | 簡單、廣泛支持、伺服器端控制 | 安全性高、易於撤銷和管理 | | 缺點 | 需要安全儲存、不易撤銷、較大大小 | 大小限制、跨域問題 | 擴展性差、負載平衡需特別處理 | | 主要適用場景 | 跨域、前後端分離、狀態無關的設計 | 單一系統、需要高安全性 | 單一系統、需要高安全性和狀態管理 | ## 什麼是 RESTful API 網路應用程式介面的設計風格,它遵循 REST(`Representational State Transfer`,具象狀態傳輸)原則:這是一種軟體架構風格,用於設計網路應用程式的互動方式,建構網路應用的設計原則和約束條件 ## 主要特點 按需求提供程式碼 Code on Demand - ### 客戶端-伺服器(Client-Server)架構 - ### 無狀態,狀態無保存(Stateless) - #### 因為每次都重新驗證用戶憑證,每個請求從客戶端到伺服器都必須包含所有必要資訊,每個請求都是獨立的,伺服器不儲存任何有關客戶端的狀態。 - ### 層次化系統(Layered System): - #### 允許在客戶端和伺服器之間增加層(如:代理、快取等) - ### 資源識別:使用 URL 路徑來標示資源 - ### 通過 HTTP 方法進行資源操作 - ### 常用的 HTTP 動詞: - `GET`:讀取資源 (READ, R) - `POST`:創建新資源(CREATE, C) - `PUT`:更新現有資源 (UPDATE, U) - `DELETE`:刪除資源 (DELETE, D) - ### 支持多種資料格式,通常是 JSON 或 XML - #### 簡單、可擴展 - ### 可快取(Cacheable):響應可以被明確地標記為可快取或不可快取。 - ### 統一介面(Uniform Interface):RESTful API 應具備一致和簡單的介面。 ## 是 RESTful 嗎 ? - ### HTTP 方法和路由: #### 根據您的程式碼,API 使用 PUT 方法進行登入操作。 #### 一般來說,登入操作更傾向於使用 POST 方法,因為它涉及到狀態變更。 - ### 狀態無保存:看起來這個 API 是狀態無保存的。 - 路由(例如 /api/user/auth)應該是名詞 # 前端 Cookie ## 設定 Cookie ```javascript! document.cookie = "username=John; expires=Wed, 1 Jan 2025 00:00:00 UTC; path=/"; ``` ## 讀取 Cookie ```javascript function getCookie(name) { const cookies = document.cookie.split("; "); for (let i = 0; i < cookies.length; i++) { const [cookieName, cookieValue] = cookies[i].split("="); if (cookieName === name) { return cookieValue; } } return null; } ``` ## 刪除 Cookie ```javascript! document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"; ``` # Node.js(使用 Express) ## 設定 Cookie ```javascript const express = require('express'); const app = express(); app.get('/set-cookie', (req, res) => { res.cookie('username', 'John', { expires: new Date(Date.now() + 86400000), httpOnly: true }); res.send('Cookie has been set'); }); ``` ## 讀取 Cookie ```javascript app.get('/read-cookie', (req, res) => { const username = req.cookies.username; res.send(`Username is ${username}`); }); ``` ## 刪除 Cookie ```javascript app.get('/delete-cookie', (req, res) => { res.clearCookie('username'); res.send('Cookie has been deleted'); }); ``` # Python(使用 Flask) ## 設定 Cookie ```python from flask import Flask, make_response app = Flask(__name__) @app.route('/set-cookie') def set_cookie(): resp = make_response('Setting cookie!') resp.set_cookie('username', 'John') return resp ``` ## 讀取 Cookie ```python from flask import Flask, request @app.route('/read-cookie') def read_cookie(): username = request.cookies.get('username') return f'Username is {username}' ``` ## 刪除 Cookie ```python @app.route('/delete-cookie') def delete_cookie(): resp = make_response('Deleting cookie!') resp.set_cookie('username', '', expires=0) return resp ``` #