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 端点):
- 
用户发送用户名和密码到 /token接口。
- 
服务器用哈希比对密码是否正确。 
- 
若正确,生成 JWT 令牌并返回给用户。 {"access_token": "xxx...", "token_type": "bearer"}
- 后续请求验证:
 用户在请求头中携带令牌(如Authorization: Bearer xxx...)。
 服务器通过依赖项get_current_user验证令牌:
- 解码令牌,检查签名和过期时间。
- 提取用户名,查询数据库确认用户存在且未被禁用。
- 若通过,返回用户信息供接口使用。
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)、权限等。
 
- 用户 ID、用户名、过期时间(
- 
例子: { "user_id": 123, "username": "Alice", "exp": 1704076800 // 过期时间(Unix 时间戳) }
- 
作用:传递用户身份和权限等信息。 (3) Signature(签名)
- 
内容:用 Header 和 Payload 的内容,加上一个 密钥(只有服务器知道),通过算法(比如 HS256)生成的字符串。
- 
作用:验证 Token 是否被篡改过,确保可信。 
3. JWT 的工作流程
假设你登录了一个网站,以下是 JWT 的工作流程:
步骤 1:登录验证
- 
你输入用户名和密码,服务器验证成功后,生成一个 JWT。 
- 
服务器把 JWT 返回给你,你保存在浏览器或 App 中。 步骤 2:携带 Token 访问其他页面
- 
你访问其他页面时,浏览器自动在请求头中带上这个 JWT(比如放在 Authorization字段):Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...步骤 3:服务器验证 Token
- 
服务器收到请求后,会做以下检查: - 
验证签名:用同样的算法和密钥,重新生成签名,对比是否一致。如果不同,说明 Token 被篡改过。 
- 
检查过期时间:如果 exp已过期,拒绝请求。
- 
解析 Payload:获取用户信息(比如用户 ID、权限)。 步骤 4:处理请求
 
- 
- 
如果验证通过,服务器就按照你的身份和权限处理请求(比如显示用户信息、允许编辑内容等)。 
4. 为什么用 JWT?
优点:
- 
无状态(Stateless):服务器不需要记录用户登录状态(比如 Session),减轻服务器负担。 
- 
跨域友好:适合移动端、单页应用(SPA)等场景。 
- 
可扩展:可以在 Payload 中添加任意信息(只要不敏感)。 缺点:
- 
信息可见:Payload 是明文(Base64 编码),虽然不可篡改,但可以被读取。不要在 Payload 中存储敏感信息(比如密码、银行卡号)。 
- 
无法撤销:一旦 Token 发出,除非过期,否则无法主动撤销。如果需要紧急下线用户,可能需要其他手段(比如黑名单)。 
5. 生活中的类比
想象你去一个需要门票的游乐场:
- 门票(JWT):由入口处的工作人员(服务器)发放。
- 门票内容:
- Header:门票类型(比如“一日票”)、编码方式。
- Payload:你的姓名、入场时间、有效期。
- Signature:工作人员盖的章,确保门票真实有效。
 
- 使用流程:
- 你买票后拿到门票(登录成功后获得 JWT)。
- 每次进入游乐场时,工作人员扫描门票(服务器验证 Token)。
- 如果门票过期或被篡改,工作人员会拒绝你。
 
总结
JWT 是一种轻量级、安全的 Token 机制,用于在客户端和服务器之间传递用户身份和信息。它通过加密签名确保数据可信,适合现代 Web 应用的无状态架构。但要注意,Payload 是可见的,不要存储敏感数据,且无法主动撤销。
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号