iT邦幫忙

2025 iThome 鐵人賽

DAY 7
0
Security

醫療數據的資安挑戰與創新解決方案系列 第 7

API Token 與角色權限控管(RBAC 實作入門)

  • 分享至 

  • xImage
  •  

今天的重點是理解 身分驗證(Authentication) 與 存取控制(Authorization) 的差別,並用 Python + JWT(JSON Web Token)示範如何設計不同角色的權限,例如「醫師」與「病人」。

一、理論重點

  1. Authentication(身分驗證)
    這是確認「你是誰」的過程。常見方式有帳號密碼、OTP 驗證碼、智慧卡,以及生物特徵辨識如指紋或人臉。舉例來說,病人輸入健保卡號與密碼登入醫院系統,系統驗證正確後才允許進入。

  2. Authorization(授權 / 存取控制)
    這是確認「你能做什麼」的規則。就算通過登入,也必須依角色決定能存取的資料。例如,病人只能看到自己的檢驗報告,而醫師可以查閱多位病人的完整病歷。

  3. RBAC(角色基礎存取控制)
    RBAC 是醫療系統最常見的授權方式。它不是針對個人設定權限,而是依角色分配。像是病人角色僅能查看自己的病歷,醫師角色能查詢所屬病人,管理員則擁有最高權限。這樣設計的好處是管理方便,新使用者只要被指派角色,就會自動繼承對應權限。

  4. JWT(JSON Web Token)
    JWT 是常見的驗證機制。當使用者登入後,系統會發給一個 Token 代表其身分。之後每次存取 API,都必須帶上這個 Token,系統才會驗證角色與權限。Token 由三部分組成:Header(演算法)、Payload(使用者資訊與角色)、Signature(數位簽章)。

二、實際案例
病患誤看他人病歷(2018,台灣)

2018 年,台灣某大型醫院的線上掛號與病歷查詢系統曾發生過資安漏洞。部分病人在登入系統後,原本應該只能看到自己的病歷,但因為程式在驗證權限時出錯,結果導致他們能意外查詢到其他病患的個人資訊與醫療紀錄。這不僅違反了個資保護相關法規,也讓病人對醫院的資訊安全產生高度質疑。事件曝光後,醫院緊急修補系統,並承諾加強 角色存取控制身份驗證機制,避免同樣狀況再發生。

三、簡單程式示範

from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel
import jwt
from datetime import datetime, timedelta

# 建立 FastAPI app
app = FastAPI()

# 假設的秘密金鑰(正式應用要放環境變數)
SECRET_KEY = "mysecretkey"
ALGORITHM = "HS256"

# 模擬的使用者資料庫
fake_users = {
    "alice": {"password": "1234", "role": "patient"},
    "bob": {"password": "5678", "role": "doctor"},
    "admin": {"password": "9999", "role": "admin"}
}

# 定義登入用的請求資料格式
class LoginRequest(BaseModel):
    username: str
    password: str

# 產生 JWT Token
def create_token(username: str, role: str):
    expire = datetime.utcnow() + timedelta(minutes=30)
    payload = {"sub": username, "role": role, "exp": expire}
    token = jwt.encode(payload, SECRET_KEY, algorithm=ALGORITHM)
    return token

# 驗證 Token
def decode_token(token: str):
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        return payload
    except jwt.ExpiredSignatureError:
        raise HTTPException(status_code=401, detail="Token expired")
    except jwt.InvalidTokenError:
        raise HTTPException(status_code=401, detail="Invalid token")

# 登入 API(不需要 client_id / client_secret)
@app.post("/login")
def login(req: LoginRequest):
    user = fake_users.get(req.username)
    if not user or user["password"] != req.password:
        raise HTTPException(status_code=401, detail="帳號或密碼錯誤")
    token = create_token(req.username, user["role"])
    return {"access_token": token}

# 病人專屬 API
@app.get("/patient")
def get_patient_data(token: str):
    payload = decode_token(token)
    if payload["role"] != "patient":
        raise HTTPException(status_code=403, detail="沒有病人權限")
    return {"message": f"Hello {payload['sub']}, 這是你的檢驗報告"}

# 醫師專屬 API
@app.get("/doctor")
def get_doctor_data(token: str):
    payload = decode_token(token)
    if payload["role"] != "doctor":
        raise HTTPException(status_code=403, detail="沒有醫師權限")
    return {"message": f"Hello {payload['sub']}, 你可以存取病人的完整病歷"}

# 管理員專屬 API
@app.get("/admin")
def get_admin_data(token: str):
    payload = decode_token(token)
    if payload["role"] != "admin":
        raise HTTPException(status_code=403, detail="沒有管理員權限")
    return {"message": f"Hello {payload['sub']}, 你擁有最高權限"}

這個範例示範了「使用者登入獲得 JWT → 每次 API 呼叫以 token 驗證 → 根據 token 內的 role 決定是否允許存取」,以簡單明確的方式模擬醫療系統中醫師與病人的 RBAC 權限管理流程。執行結果如下
https://ithelp.ithome.com.tw/upload/images/20250916/201693310OTWWMfcel.pnghttps://ithelp.ithome.com.tw/upload/images/20250916/20169331E0bFEHvyPd.pnghttps://ithelp.ithome.com.tw/upload/images/20250916/20169331ZWBtONePBn.png


上一篇
醫療物聯網(IoMT)資安挑戰與防護
下一篇
醫療 IoT 裝置的資安挑戰
系列文
醫療數據的資安挑戰與創新解決方案10
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言