如何用Python验证Laravel Passport生成的访问令牌?
验证Laravel Passport令牌(Python端共享数据库场景)
因为你的Python项目和Laravel共享数据库,不需要向Laravel发起验证请求,可根据Passport令牌的类型选择两种方案:
方案1:验证JWT格式令牌(密码授权模式)
如果你的令牌是Laravel Passport密码授权生成的JWT格式,直接用Python的JWT库解析验证即可:
- 从Laravel项目中获取公钥(路径为
storage/oauth-public.key) - 安装依赖库:
pip install pyjwt cryptography
- 验证代码示例:
import jwt from jwt.exceptions import InvalidTokenError from datetime import datetime def validate_jwt_token(token): # 加载Laravel Passport公钥 with open("/path/to/oauth-public.key", "r") as f: public_key = f.read() try: # 解析并验证令牌,RS256是Passport默认的加密算法 payload = jwt.decode( token, public_key, algorithms=["RS256"], options={"verify_aud": False} # 根据你的Passport配置决定是否验证aud字段 ) # 额外检查令牌是否过期(pyjwt默认会自动验证exp) if datetime.utcfromtimestamp(payload["exp"]) < datetime.utcnow(): return False, "Token expired" return True, payload except InvalidTokenError as e: return False, str(e)
方案2:验证个人访问令牌(随机字符串格式)
如果是Passport默认的个人访问令牌(非JWT的随机字符串),直接查询共享数据库的oauth_access_tokens表验证:
- 安装数据库依赖(以MySQL为例):
pip install pymysql
- 验证代码示例:
import pymysql from datetime import datetime def validate_personal_token(token, db_config): conn = pymysql.connect(**db_config) cursor = conn.cursor(pymysql.cursors.DictCursor) # 查询令牌是否存在、未撤销、未过期 query = """ SELECT id FROM oauth_access_tokens WHERE id = %s AND revoked = 0 AND expires_at > %s """ cursor.execute(query, (token, datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S"))) result = cursor.fetchone() cursor.close() conn.close() return result is not None # 调用示例 db_config = { "host": "你的数据库地址", "user": "数据库用户名", "password": "数据库密码", "db": "共享数据库名" } is_valid = validate_personal_token("你的令牌字符串", db_config)
实现Python项目的验证中间件(以FastAPI为例)
把验证逻辑封装成中间件/依赖,方便在路由中复用:
from fastapi import Depends, HTTPException, Request async def auth_middleware(request: Request): auth_header = request.headers.get("Authorization") if not auth_header or not auth_header.startswith("Bearer "): raise HTTPException(status_code=401, detail="无效的授权头") token = auth_header.split(" ")[1] # 根据你的令牌类型选择验证函数 is_valid, payload = validate_jwt_token(token) # 或者 is_valid = validate_personal_token(token, db_config) if not is_valid: raise HTTPException(status_code=401, detail="令牌无效或已过期") return payload # 受保护的路由示例 @app.get("/api/protected") async def protected_route(user_info=Depends(auth_middleware)): return {"message": "已通过验证", "user_id": user_info["sub"]}
注意事项
- 确保Python项目有读取
oauth_access_tokens表的数据库权限 - 使用JWT验证时,要同步Laravel的公钥,避免公钥更新后验证失败
- 处理时间时统一用UTC时间,避免时区差异导致过期判断错误
内容的提问来源于stack exchange,提问作者Felipe Castillo
相关产品推荐
相关产品推荐

