Fastapi密码

1. 密码哈希:保护用户密码不被泄露

  • 为什么需要哈希?
    如果把密码直接存成明文(比如“123456”),一旦数据库被黑客窃取,所有密码都会暴露。
    哈希就是把密码转换成一段乱码(比如“$2b\(12\)...”),且无法反向还原。即使数据库泄露,黑客也无法知道原始密码。
  • 如何实现?
    使用 Passlib 库和 Bcrypt 算法:
  • 存储密码时:输入明文密码 → 生成哈希值(如 get_password_hash("密码"))。
  • 验证密码时:输入明文密码 → 与数据库中的哈希值对比(如 verify_password(输入的密码, 哈希值))。

2. JWT 令牌:安全传递用户身份

  • 什么是 JWT?
    JWT(JSON Web Token)是一个加密的“通行证”,包含用户信息(如用户名、过期时间等),并用密钥签名。

  • 内容不可篡改:如果有人修改了令牌,服务器会通过签名发现并拒绝它。

  • 有效期:比如设置令牌 30 分钟后过期,过期后需重新登录获取新令牌。

  • 如何生成和验证?
    使用 PyJWT 库:

  • 生成令牌:用户登录成功后,用密钥(SECRET_KEY)生成 JWT,返回给用户。

    create_access_token(data={"sub": "用户名"}, expires_delta=30分钟)
    
    • 验证令牌:用户每次请求时携带令牌,服务器解码并校验签名是否合法、是否过期。

      # 验证逻辑:尝试解码 → 检查签名 → 获取用户名 → 查询用户是否存在
      

3. OAuth2 流程:用户登录与权限验证

  • 登录流程(/token 端点)
  1. 用户发送用户名和密码到 /token 接口。

  2. 服务器用哈希比对密码是否正确。

  3. 若正确,生成 JWT 令牌并返回给用户。

    {"access_token": "xxx...", "token_type": "bearer"}
    
  • 后续请求验证
    用户在请求头中携带令牌(如 Authorization: Bearer xxx...)。
    服务器通过依赖项 get_current_user 验证令牌:
  1. 解码令牌,检查签名和过期时间。
  2. 提取用户名,查询数据库确认用户存在且未被禁用。
  3. 若通过,返回用户信息供接口使用。

4. 关键代码流程

用户登录(获取令牌)

@app.post("/token")
async def login_for_access_token(form_data: OAuth2PasswordRequestForm):
 # 1. 验证用户名和密码(密码哈希比对)
 user = authenticate_user(form_data.username, form_data.password)
 if not user:
 raise HTTPException(status_code=401, detail="用户名或密码错误")

# 2. 生成 JWT 令牌

 access_token = create_access_token(data={"sub": user.username})
 return {"access_token": access_token, "token_type": "bearer"}

验证当前用户

async def get_current_user(token: str = Depends(oauth2_scheme)):
 try:
 # 1. 解码 JWT 令牌,获取用户名
 payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
 username = payload.get("sub")

# 2. 查询用户是否存在
 user = get_user(username)
 if not user:
 raise HTTPException(status_code=401, detail="无效用户")
 except:
 raise HTTPException(status_code=401, detail="令牌无效")
 return user

5. 总结

  • 密码哈希:保护密码不被泄露,用 Passlib 处理。
  • JWT 令牌:安全传递用户身份,用 PyJWT 生成和验证。
  • OAuth2 流程:用户登录获取令牌 → 后续请求携带令牌 → 服务器验证令牌合法性。
    通过这些步骤,用户可以安全地登录并访问受保护的接口,同时避免了明文密码存储和频繁输入密码的麻烦。

1. JWT 是什么?

JWT(全称 JSON Web Token)是一种 轻量级的、用于在客户端和服务器之间传递信息 的技术。它的核心作用是 身份验证和信息传递,比如登录后保持用户状态、在不同服务间传递用户信息等。

举个例子:

想象你去餐厅吃饭,服务员给你一张写着“已付款”的纸条。这张纸条就是你的“通行证”,你可以凭它去取餐、续杯,而服务员不需要每次都重新核对你的身份。
JWT 就像这张纸条,但它是用加密的方式生成的,只有特定的人(服务器)才能验证它的有效性。


2. JWT 的结构

JWT 由三部分组成,用点号(.)分隔,格式是:
header.payload.signature

(1) Header(头部)

  • 内容:通常包含两样东西:

    • 算法(比如 HS256,一种加密算法)。
    • 类型(固定是 JWT)。
  • 例子

    {
    "alg": "HS256",
    "typ": "JWT"
    }
    
  • 作用:告诉服务器如何处理这个 Token。

    (2) Payload(载荷)

  • 内容:存储用户信息和声明(claims),比如:

    • 用户 ID、用户名、过期时间(exp)、权限等。
  • 例子

    {
    "user_id": 123,
    "username": "Alice",
    "exp": 1704076800 // 过期时间(Unix 时间戳)
    }
    
  • 作用:传递用户身份和权限等信息。

    (3) Signature(签名)

  • 内容:用 HeaderPayload 的内容,加上一个 密钥(只有服务器知道),通过算法(比如 HS256)生成的字符串。

  • 作用:验证 Token 是否被篡改过,确保可信。


3. JWT 的工作流程

假设你登录了一个网站,以下是 JWT 的工作流程:

步骤 1:登录验证

  • 你输入用户名和密码,服务器验证成功后,生成一个 JWT。

  • 服务器把 JWT 返回给你,你保存在浏览器或 App 中。

    步骤 2:携带 Token 访问其他页面

  • 你访问其他页面时,浏览器自动在请求头中带上这个 JWT(比如放在 Authorization 字段):

    Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
    

    步骤 3:服务器验证 Token

  • 服务器收到请求后,会做以下检查:

    1. 验证签名:用同样的算法和密钥,重新生成签名,对比是否一致。如果不同,说明 Token 被篡改过。

    2. 检查过期时间:如果 exp 已过期,拒绝请求。

    3. 解析 Payload:获取用户信息(比如用户 ID、权限)。

      步骤 4:处理请求

  • 如果验证通过,服务器就按照你的身份和权限处理请求(比如显示用户信息、允许编辑内容等)。


4. 为什么用 JWT?

优点:

  1. 无状态(Stateless):服务器不需要记录用户登录状态(比如 Session),减轻服务器负担。

  2. 跨域友好:适合移动端、单页应用(SPA)等场景。

  3. 可扩展:可以在 Payload 中添加任意信息(只要不敏感)。

    缺点:

  4. 信息可见:Payload 是明文(Base64 编码),虽然不可篡改,但可以被读取。不要在 Payload 中存储敏感信息(比如密码、银行卡号)。

  5. 无法撤销:一旦 Token 发出,除非过期,否则无法主动撤销。如果需要紧急下线用户,可能需要其他手段(比如黑名单)。


5. 生活中的类比

想象你去一个需要门票的游乐场:

  • 门票(JWT):由入口处的工作人员(服务器)发放。
  • 门票内容
    • Header:门票类型(比如“一日票”)、编码方式。
    • Payload:你的姓名、入场时间、有效期。
    • Signature:工作人员盖的章,确保门票真实有效。
  • 使用流程
    1. 你买票后拿到门票(登录成功后获得 JWT)。
    2. 每次进入游乐场时,工作人员扫描门票(服务器验证 Token)。
    3. 如果门票过期或被篡改,工作人员会拒绝你。

总结

JWT 是一种轻量级、安全的 Token 机制,用于在客户端和服务器之间传递用户身份和信息。它通过加密签名确保数据可信,适合现代 Web 应用的无状态架构。但要注意,Payload 是可见的,不要存储敏感数据,且无法主动撤销。

posted @ 2025-03-17 23:19  玉米面手雷王  阅读(44)  评论(0)    收藏  举报