On this page
Authentication
ทำให้แอป "รู้ว่าใครเป็นใคร" — login, hash รหัสผ่าน, และป้องกัน endpoint ด้วย token
แอปจริงเกือบทุกตัวต้องรู้ว่าผู้ใช้คนไหนกำลังเรียก เพื่อแสดงข้อมูลของเขาและจำกัดสิทธิ์ หัวข้อนี้ปูพื้นฐาน authentication: เก็บรหัสผ่านอย่างปลอดภัย, login, และป้องกัน endpoint
session vs token
| แบบ | หลักการ | เก็บที่ |
|---|---|---|
| Session | server จำว่าใคร login ผ่าน session id | server (+cookie) |
| Token (JWT) | client ถือ token ที่ลงนามไว้ ส่งมาทุก request | client |
API สมัยใหม่นิยม token (JWT) เพราะ stateless — server ไม่ต้องจำ session แค่ตรวจลายเซ็น token ที่ client ส่งมา
hash รหัสผ่าน — ห้ามเก็บ plaintext
เก็บรหัสผ่านเป็นข้อความตรง ๆ คือหายนะ ถ้า DB หลุดผู้ใช้ทุกคนซวย ต้อง hash (แปลงทางเดียว) + salt เสมอ — ตอน login เอารหัสที่กรอกมา hash แล้วเทียบ
from passlib.hash import bcrypt # pip install passlib bcrypt
# ตอนสมัคร: hash ก่อนเก็บ
hashed = bcrypt.hash("my_password")
print(hashed) # $2b$12$.... (เก็บค่านี้ใน DB ไม่ใช่รหัสจริง)
# ตอน login: ตรวจรหัสที่กรอกกับ hash ที่เก็บไว้
bcrypt.verify("my_password", hashed) # True
bcrypt.verify("wrong", hashed) # Falseห้ามเก็บรหัสผ่านตรง ๆ และห้าม hash แบบธรรมดา (เช่น md5/sha1 เปล่า ๆ) ใช้ bcrypt/argon2 ที่ออกแบบมาเพื่อรหัสผ่านโดยเฉพาะ (ช้าโดยตั้งใจ + มี salt) นี่คือมาตรฐานขั้นต่ำที่ละเมิดไม่ได้
login flow & ป้องกัน endpoint
ภาพรวม: ผู้ใช้ส่ง user/pass → server ตรวจ → ออก token → client เก็บ token แล้วแนบใน header ทุก request → server ตรวจ token ก่อนให้เข้า endpoint ที่ป้องกันไว้
from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer
app = FastAPI()
oauth2 = OAuth2PasswordBearer(tokenUrl="login")
def get_current_user(token: str = Depends(oauth2)):
user = verify_token(token) # ตรวจ/ถอด token
if user is None:
raise HTTPException(status_code=401, detail="ยังไม่ได้ล็อกอิน")
return user
@app.get("/me")
def read_me(user = Depends(get_current_user)): # endpoint ที่ต้อง login
return {"user": user}สรุปหัวข้อนี้
- authentication = รู้ว่าใครเป็นใคร; API นิยม token (JWT, stateless)
- hash รหัสผ่านด้วย bcrypt/argon2 + salt เสมอ — ห้ามเก็บ plaintext
- ตอน login เทียบรหัสที่กรอกกับ hash (verify) ไม่ถอดรหัสกลับ
- ป้องกัน endpoint ด้วย dependency ที่ตรวจ token (401 ถ้าไม่ผ่าน)
1) เขียนฟังก์ชัน register ที่ hash รหัสผ่านด้วย bcrypt ก่อนเก็บ 2) เขียน login ที่ verify รหัสกับ hash 3) ทำ endpoint /me ที่ต้องมี token 4) อธิบายว่าทำไมห้ามเก็บรหัสผ่านเป็น plaintext