# auth.py
# 教學用最小登入系統(Python + SQLite)
# 特點:
# - 只用一個 users 資料表(username 唯一、password 明碼)
# - 無 sessions、無防暴力破解
# - 內含:建表、註冊、登入、列出使用者
import sqlite3
from pathlib import Path
DB_PATH = Path(__file__).with_name("auth_demo.db")
DDL_USERS = """
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL UNIQUE,
password TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
"""
def get_conn():
conn = sqlite3.connect(DB_PATH)
conn.execute("PRAGMA foreign_keys = ON;")
return conn
def init_db():
with get_conn() as conn:
conn.execute(DDL_USERS)
print("資料庫初始化完成(若不存在則建立 users 資料表)。")
def register_user(username: str, password: str) -> bool:
"""註冊新使用者(密碼明碼;教學用)"""
try:
with get_conn() as conn:
conn.execute(
"INSERT INTO users (username, password) VALUES (?, ?);",
(username, password),
)
return True
except sqlite3.IntegrityError:
return False
def verify_login(username: str, password: str) -> bool:
"""一次性登入驗證(比對明碼;教學用)"""
with get_conn() as conn:
row = conn.execute(
"SELECT password FROM users WHERE username = ?;",
(username,),
).fetchone()
if row is None:
return False
return password == row[0]
def list_users():
"""列出所有使用者(會顯示明碼密碼,僅供教學觀察!)"""
with get_conn() as conn:
rows = conn.execute(
"SELECT id, username, password, created_at FROM users ORDER BY id;"
).fetchall()
if not rows:
print("(目前沒有使用者)")
return
print("\n=== 使用者清單(教學用,含明碼) ===")
for rid, uname, pwd, ctime in rows:
print(f"[{rid}] {uname:15s} 密碼: {pwd:10s} 建立時間: {ctime}")
print("=================================\n")
def seed_demo_user():
"""建立一個示範帳號 admin/admin(若不存在)"""
with get_conn() as conn:
row = conn.execute("SELECT 1 FROM users WHERE username='admin';").fetchone()
if row is None:
conn.execute(
"INSERT INTO users (username, password) VALUES (?, ?);",
("admin", "admin"),
)
print("已建立示範帳號:username=admin / password=admin")
def main_menu():
while True:
print("\n=== 簡易登入系統(教學用)===")
print("1) 註冊帳號")
print("2) 登入系統")
print("3) 查詢帳號")
print("0) 離開")
choice = input("請選擇:").strip()
if choice == "1":
u = input("請輸入帳號:").strip()
p = input("請輸入密碼:").strip()
if not u or not p:
print("帳號與密碼不可為空!")
continue
ok = register_user(u, p)
print("註冊成功!" if ok else "帳號已存在,請改用其他帳號。")
elif choice == "2":
u = input("請輸入帳號:").strip()
p = input("請輸入密碼:").strip()
ok = verify_login(u, p)
print("登入成功!" if ok else "登入失敗,帳號或密碼錯誤。")
elif choice == "3":
list_users()
elif choice == "0":
print("Bye ~")
break
else:
print("請輸入有效選項。")
if __name__ == "__main__":
init_db()
seed_demo_user() # 預設建立 admin/1234 帳號
main_menu()