# 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
```
#