---
# System prepended metadata

title: JWT 實作認證（上） - 原理介紹

---

# JWT（上）- Session, Cookie 差別與概念

## 前言
在寫登入系統的時候都會遇到一些驗證的問題，登入後怎麼確保使用者個資不會被篡改？還有怎麼確定是不是原本的使用者？確定資料有沒有被篡改？方式有很多，舉凡session, cookie等都是常用的驗證機制，本篇將為大家介紹上述認證機制的差異，以及JWT的運作流程。

## Session和JWT是什麼？

### 什麼時候用到？
當我們登入一個網站的時候，如果關掉再打開就要重新登入，使用者當然會覺得很不方便，所以需要一個像是便條紙的功能，貼在使用者的網站瀏覽器上，下一次使用者又打開網站的時候，系統會先去看便條紙上有沒有東西，如果有紀錄使用者id或是其他資料就代表之前登入過了，如果沒有才會要求重新登入。

### Session 和 jwt
兩者功能其實非常類似，都是將資訊儲存起來，讓使用者不用每次都要重新登入，或是記錄一些動作，前者像一個會員卡，上面只有編號，後端確認過編號後才會從資料庫中尋找隊員卡編號對應的資料，後者就像前面提到的便條貼，把所有的東西寫在上面存在前端，後端可以直接從便條貼上判斷資料有無錯誤，並且回傳對應的資料。



## JWT 機制
JWT 的全名是 JSON Web Token，是一種基於 JSON 的開放標準(RFC 7519)，它定義了一種簡潔(compact)且自包含(self-contained)的方式，用於在雙方之間安全地將訊息作為 JSON 物件傳輸。使用者登入後發送一個要求到後端，後端產生一個JWT後回傳前端，並儲存在瀏覽器的在Local Storage中，前端要取得資料時，將JWT發送到後端，讓伺服器判斷有沒有被修改，認證成功就會把資料回傳給前端。

![](https://hackmd.io/_uploads/r1jX_thxa.png)


### 組成
透過（.）連接三個Base64編碼的字串，分別是：

- Header：包含兩個欄位Token得種類和雜湊演算法
  ```
  {
    "alg": "HS256", 
    "typ": "JWT"
  } 
  ```
- Payload：存放需要的資訊（例如使用者id）
    - exp和iat代表 token 到期和啟用的時間
    - payload內可以自訂要放的資訊
  ```
  {
    "payload": {
        "user_id": 3,
        "user_name": "hello world",
      },
      "exp": 1696532042,
      "iat": 1696528442
  }
  ```
  
    :::info
    :warning: payload中不要存放敏感性或機密資料，因為payload是明文，可以輕易被看到，jwt的重點是不可篡改性，而不是加密！
    如果真的需要加密資訊，可以考慮使用AES對稱加密法來實作～
    :::
  
  
- Signature：編譯後的 Header、Payload 與密鑰透過雜湊演算法所產生
  ```
  HMACSHA256(
      base64UrlEncode(header) + "." +
      base64UrlEncode(payload), 
        your-secret
    )
  ```
    :::info
    :writing_hand: your-secret是加密的鑰匙，通常存在後端，比較不容易被他人取得，一旦洩漏別人就可以輕易產生jwt了啊！
    :::
    
    
### 編碼
將上面三個部分分別用Base 64編碼，並且用 . 分隔，就可以得到專屬的jwt了！
```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
```

想要更快解密jwt可以點進[JWT 網站](https://jwt.io/)，只要把jwt貼到上面就會自動幫你用base 64 解碼，由此可知放在上面的東西可以容易被看到的！

![](https://hackmd.io/_uploads/ryJzQuhxa.png)


### 認證
回到前面便條紙的例子，現在知道有JWT的便條紙且上面又有寫字，但問題又來了，怎麼確保便條紙上面的東西沒有被別人用橡皮擦或立可白修改過呢？

前面有提到第三部分Signature是由header和payload搭配密鑰產生的，換言之要是payload有被修改過，Signature的值也會不一樣，後端解密的過程中藉此來判斷有沒有被修改過！如果後端能透過密鑰解碼成功，前端使用者就可以直接拿到資訊，如果失敗就代表token已經被竄改了，因此不需要再和資料庫連接比對是否是對的token，減少伺服器本身的負擔，這種驗證方式也稱為無狀態驗證。


## 總結
總之Session和JWT各有好壞，沒有哪一個是絕對好的，還是要依自己的需求而定，因為筆者比較常用js寫前後端，再加上大部分的都用restful api所以主要以jwt為主，有興趣的人可以再看看下一篇 [JWT（下）- 實作認證 React, Node.js](https://hackmd.io/@emmmmmma/rynNZO2g6) 了解實際的應用！


## 參考
- [JWT(JSON Web Token) — 原理介紹](https://medium.com/%E4%BC%81%E9%B5%9D%E4%B9%9F%E6%87%82%E7%A8%8B%E5%BC%8F%E8%A8%AD%E8%A8%88/jwt-json-web-token-%E5%8E%9F%E7%90%86%E4%BB%8B%E7%B4%B9-74abfafad7ba)
- [你的網站是怎麼管理登出登入的呢：Cookie-Session驗證和 JWT驗證機制的差別](https://medium.com/rae-lee/%E4%BD%A0%E7%9A%84%E7%B6%B2%E7%AB%99%E6%98%AF%E6%80%8E%E9%BA%BC%E7%AE%A1%E7%90%86%E7%99%BB%E5%87%BA%E7%99%BB%E5%85%A5%E7%9A%84%E5%91%A2-cookie-session%E9%A9%97%E8%AD%89%E5%92%8C-jwt%E9%A9%97%E8%AD%89%E6%A9%9F%E5%88%B6%E7%9A%84%E5%B7%AE%E5%88%A5-50f60f4d5952)
- [用户认证：基于jwt和session的区别和优缺点](https://zhuanlan.zhihu.com/p/108999941)
- [JWT tokens and security – working principles and use cases](https://www.vaadata.com/blog/jwt-tokens-and-security-working-principles-and-use-cases/)