当前位置:首页>python>Python Web开发:认证授权

Python Web开发:认证授权

  • 2026-06-28 05:56:17
Python Web开发:认证授权
副标题

: 90%的人不知道,JWT令牌能让你的API安全又简单

痛点:为什么你的API总是担心被滥用?

2025年某项目API被恶意调用,数据泄露。问题出在哪?工程师没有实现完善的认证授权机制。

真相

:认证(你是谁)和授权(你能做什么)是API安全的基石。

方案适用场景推荐度
Session传统Web应用⭐⭐⭐
JWTAPI/移动端⭐⭐⭐⭐⭐
OAuth2第三方登录⭐⭐⭐⭐
API Key服务间调用⭐⭐⭐

一、JWT基础

1.1 什么是JWT

JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在各方之间安全地传输信息。

JWT结构: Header.Payload.Signature

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.

SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

1.2 JWT生成与验证

import jwt

from datetime import datetime, timedelta

from typing import Optional

SECRET_KEY = "your-secret-key-change-in-production"

ALGORITHM = "HS256"

ACCESS_TOKEN_EXPIRE_MINUTES = 30

def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):

"""创建访问令牌"""

to_encode = data.copy()

if expires_delta:

expire = datetime.utcnow() + expires_delta

else:

expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)

to_encode.update({"exp": expire})

encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)

return encoded_jwt

def verify_token(token: str) -> Optional[dict]:

"""验证令牌"""

try:

payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])

return payload

except jwt.ExpiredSignatureError:

return None

except jwt.InvalidTokenError:

return None

使用

token = create_access_token({"sub": "user123", "username": "alice"})

payload = verify_token(token)

print(payload) # {'sub': 'user123', 'username': 'alice', 'exp': ...}

1.3 JWT在FastAPI中使用

from fastapi import FastAPI, Depends, HTTPException, status

from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm

from pydantic import BaseModel

import jwt

from datetime import datetime, timedelta

app = FastAPI()

SECRET_KEY = "your-secret-key"

ALGORITHM = "HS256"

ACCESS_TOKEN_EXPIRE_MINUTES = 30

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

class Token(BaseModel):

access_token: str

token_type: str

class TokenData(BaseModel):

username: str | None = None

def create_access_token(data: dict):

to_encode = data.copy()

expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)

to_encode.update({"exp": expire})

return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)

def get_current_user(token: str = Depends(oauth2_scheme)):

credentials_exception = HTTPException(

status_code=status.HTTP_401_UNAUTHORIZED,

detail="Could not validate credentials",

headers={"WWW-Authenticate": "Bearer"},

)

try:

payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])

username: str = payload.get("sub")

if username is None:

raise credentials_exception

token_data = TokenData(username=username)

except jwt.ExpiredSignatureError:

raise credentials_exception

except jwt.InvalidTokenError:

raise credentials_exception

return token_data

@app.post("/token", response_model=Token)

async def login(form_data: OAuth2PasswordRequestForm = Depends()):

# 验证用户名密码

if form_data.username != "alice" or form_data.password != "password":

raise HTTPException(

status_code=status.HTTP_401_UNAUTHORIZED,

detail="Incorrect username or password",

headers={"WWW-Authenticate": "Bearer"},

)

access_token = create_access_token({"sub": form_data.username})

return Token(access_token=access_token, token_type="bearer")

@app.get("/users/me")

async def read_users_me(current_user: TokenData = Depends(get_current_user)):

return {"username": current_user.username}

二、密码哈希

2.1 使用Passlib

pip install passlib[bcrypt]
from passlib.context import CryptContext

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

def verify_password(plain_password: str, hashed_password: str) -> bool:

"""验证密码"""

return pwd_context.verify(plain_password, hashed_password)

def get_password_hash(password: str) -> str:

"""生成密码哈希"""

return pwd_context.hash(password)

使用

hashed = get_password_hash("mypassword")

print(verify_password("mypassword", hashed)) # True

print(verify_password("wrong", hashed)) # False

2.2 密码强度验证

import re

def validate_password_strength(password: str) -> tuple[bool, str]:

"""验证密码强度"""

if len(password) < 8:

return False, "密码长度至少8位"

if not re.search(r"[a-z]", password):

return False, "密码必须包含小写字母"

if not re.search(r"[A-Z]", password):

return False, "密码必须包含大写字母"

if not re.search(r"\d", password):

return False, "密码必须包含数字"

if not re.search(r"[!@#$%^&*]", password):

return False, "密码必须包含特殊字符"

return True, "密码强度合格"

使用

is_valid, message = validate_password_strength("MyP@ssw0rd")

print(f"{is_valid}: {message}")

三、角色权限

3.1 基于角色的访问控制(RBAC)

from fastapi import Depends, HTTPException, status

from typing import List

class PermissionChecker:

"""权限检查器"""

def __init__(self, required_roles: List[str]):

self.required_roles = required_roles

def __call__(self, current_user: dict = Depends(get_current_user)):

user_roles = current_user.get("roles", [])

if not any(role in self.required_roles for role in user_roles):

raise HTTPException(

status_code=status.HTTP_403_FORBIDDEN,

detail="不允许访问"

)

return current_user

使用

@app.get("/admin/users")

async def get_admin_users(

user: dict = Depends(PermissionChecker(["admin"]))

):

return {"message": "管理员页面"}

@app.get("/manager/reports")

async def get_manager_reports(

user: dict = Depends(PermissionChecker(["admin", "manager"]))

):

return {"message": "经理页面"}

3.2 权限装饰器

from functools import wraps

from fastapi import HTTPException, status

def require_role(*roles):

"""角色装饰器"""

def decorator(func):

@wraps(func)

async def wrapper(args, current_user: dict = Depends(get_current_user), *kwargs):

user_roles = current_user.get("roles", [])

if not any(role in roles for role in user_roles):

raise HTTPException(

status_code=status.HTTP_403_FORBIDDEN,

detail="权限不足"

)

return await func(args, current_user=current_user, *kwargs)

return wrapper

return decorator

使用

@app.get("/admin/dashboard")

@require_role("admin")

async def admin_dashboard(current_user: dict = Depends(get_current_user)):

return {"message": "管理员仪表盘"}

3.3 权限模型

from pydantic import BaseModel

from typing import List

from enum import Enum

class ResourceType(str, Enum):

USER = "user"

ITEM = "item"

REPORT = "report"

class Action(str, Enum):

CREATE = "create"

READ = "read"

UPDATE = "update"

DELETE = "delete"

class Permission(BaseModel):

resource: ResourceType

action: Action

class Role(BaseModel):

name: str

permissions: List[Permission]

class User(BaseModel):

id: int

username: str

roles: List[Role]

预定义角色

ADMIN_PERMISSIONS = [

Permission(resource=ResourceType.USER, action=Action.READ),

Permission(resource=ResourceType.USER, action=Action.CREATE),

Permission(resource=ResourceType.USER, action=Action.UPDATE),

Permission(resource=ResourceType.USER, action=Action.DELETE),

Permission(resource=ResourceType.ITEM, action=Action.READ),

Permission(resource=ResourceType.ITEM, action=Action.CREATE),

Permission(resource=ResourceType.ITEM, action=Action.UPDATE),

Permission(resource=ResourceType.ITEM, action=Action.DELETE),

Permission(resource=ResourceType.REPORT, action=Action.READ),

]

ADMIN_ROLE = Role(name="admin", permissions=ADMIN_PERMISSIONS)

def check_permission(user: User, resource: ResourceType, action: Action) -> bool:

"""检查用户是否有权限"""

for role in user.roles:

for perm in role.permissions:

if perm.resource == resource and perm.action == action:

return True

return False

四、OAuth2集成

4.1 Google OAuth2

from fastapi import FastAPI, Depends, HTTPException

from fastapi.security import OAuth2AuthorizationCodeBearer

import httpx

app = FastAPI()

GOOGLE_CLIENT_ID = "your-client-id"

GOOGLE_CLIENT_SECRET = "your-client-secret"

GOOGLE_REDIRECT_URI = "http://localhost:8000/callback"

oauth2_scheme = OAuth2AuthorizationCodeBearer(

authorizationUrl="https://accounts.google.com/o/oauth2/v2/auth",

tokenUrl="https://oauth2.googleapis.com/token",

)

@app.get("/login/google")

async def google_login():

"""生成Google登录URL"""

auth_url = (

f"https://accounts.google.com/o/oauth2/v2/auth?"

f"client_id={GOOGLE_CLIENT_ID}&"

f"redirect_uri={GOOGLE_REDIRECT_URI}&"

f"response_type=code&"

f"scope=openid%20email%20profile"

)

return {"url": auth_url}

@app.get("/callback")

async def callback(code: str):

"""处理回调"""

async with httpx.AsyncClient() as client:

response = await client.post(

"https://oauth2.googleapis.com/token",

data={

"client_id": GOOGLE_CLIENT_ID,

"client_secret": GOOGLE_CLIENT_SECRET,

"code": code,

"redirect_uri": GOOGLE_REDIRECT_URI,

"grant_type": "authorization_code",

},

)

tokens = response.json()

access_token = tokens.get("access_token")

# 获取用户信息

async with httpx.AsyncClient() as client:

user_response = await client.get(

"https://www.googleapis.com/oauth2/v2/userinfo",

headers={"Authorization": f"Bearer {access_token}"},

)

user_info = user_response.json()

return user_info

4.2 GitHub OAuth2

GITHUB_CLIENT_ID = "your-client-id"

GITHUB_CLIENT_SECRET = "your-client-secret"

@app.get("/login/github")

async def github_login():

auth_url = (

f"https://github.com/login/oauth/authorize?"

f"client_id={GITHUB_CLIENT_ID}&"

f"redirect_uri={GOOGLE_REDIRECT_URI}&"

f"scope=user:email"

)

return {"url": auth_url}

@app.get("/github/callback")

async def github_callback(code: str):

async with httpx.AsyncClient() as client:

response = await client.post(

"https://github.com/login/oauth/access_token",

data={

"client_id": GITHUB_CLIENT_ID,

"client_secret": GITHUB_CLIENT_SECRET,

"code": code,

},

headers={"Accept": "application/json"},

)

tokens = response.json()

access_token = tokens.get("access_token")

async with httpx.AsyncClient() as client:

user_response = await client.get(

"https://api.github.com/user",

headers={"Authorization": f"token {access_token}"},

)

return user_response.json()

五、会话管理

5.1 Session存储

from fastapi import FastAPI, Request

from fastapi.responses import JSONResponse

import secrets

from datetime import datetime, timedelta

from typing import Dict, Optional

app = FastAPI()

内存存储(生产环境用Redis)

sessions: Dict[str, dict] = {}

SESSION_EXPIRE_HOURS = 24

def generate_session_id() -> str:

return secrets.token_urlsafe(32)

def create_session(user_id: int) -> str:

session_id = generate_session_id()

sessions[session_id] = {

"user_id": user_id,

"created_at": datetime.utcnow(),

"expires_at": datetime.utcnow() + timedelta(hours=SESSION_EXPIRE_HOURS),

}

return session_id

def get_session(session_id: str) -> Optional[dict]:

session = sessions.get(session_id)

if not session:

return None

if datetime.utcnow() > session["expires_at"]:

del sessions[session_id]

return None

return session

def delete_session(session_id: str):

sessions.pop(session_id, None)

@app.post("/login")

async def login(username: str, password: str, request: Request):

# 验证用户

if username != "alice" or password != "password":

return JSONResponse(status_code=401, content={"detail": "Invalid credentials"})

session_id = create_session(user_id=1)

# 设置Cookie

response = JSONResponse(content={"session_id": session_id})

response.set_cookie(

key="session_id",

value=session_id,

max_age=SESSION_EXPIRE_HOURS * 3600,

httponly=True,

secure=True, # 生产环境用HTTPS

samesite="lax",

)

return response

@app.get("/profile")

async def get_profile(request: Request):

session_id = request.cookies.get("session_id")

if not session_id:

return JSONResponse(status_code=401, content={"detail": "Not authenticated"})

session = get_session(session_id)

if not session:

return JSONResponse(status_code=401, content={"detail": "Session expired"})

return {"user_id": session["user_id"]}

@app.post("/logout")

async def logout(request: Request):

session_id = request.cookies.get("session_id")

if session_id:

delete_session(session_id)

response = JSONResponse(content={"message": "Logged out"})

response.delete_cookie("session_id")

return response

5.2 刷新令牌

from datetime import datetime, timedelta

import jwt

REFRESH_TOKEN_EXPIRE_DAYS = 7

def create_refresh_token(data: dict) -> str:

"""创建刷新令牌"""

to_encode = data.copy()

expire = datetime.utcnow() + timedelta(days=REFRESH_TOKEN_EXPIRE_DAYS)

to_encode.update({"exp": expire, "type": "refresh"})

return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)

def refresh_access_token(refresh_token: str) -> str:

"""刷新访问令牌"""

try:

payload = jwt.decode(refresh_token, SECRET_KEY, algorithms=[ALGORITHM])

if payload.get("type") != "refresh":

raise HTTPException(status_code=401, detail="Invalid token type")

username = payload.get("sub")

if not username:

raise HTTPException(status_code=401, detail="Invalid token")

return create_access_token({"sub": username})

except jwt.ExpiredSignatureError:

raise HTTPException(status_code=401, detail="Refresh token expired")

except jwt.InvalidTokenError:

raise HTTPException(status_code=401, detail="Invalid refresh token")

@app.post("/token/refresh")

async def refresh_token(refresh_token: str):

new_access_token = refresh_access_token(refresh_token)

return {"access_token": new_access_token, "token_type": "bearer"}

六、安全最佳实践

6.1 密码存储

# ✅ 好的做法

from passlib.context import CryptContext

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

使用bcrypt,自动加盐

hashed = pwd_context.hash(password)

❌ 不好的做法

明文存储

使用弱哈希(MD5、SHA1)

不加盐

6.2 令牌安全

# ✅ 好的做法

使用HTTPS

设置合理的过期时间

使用HttpOnly Cookie

实现令牌黑名单

❌ 不好的做法

在URL中传递令牌

令牌永不过期

存储敏感信息在令牌中

6.3 速率限制

from fastapi import FastAPI, Request, HTTPException

from collections import defaultdict

from datetime import datetime, timedelta

import time

app = FastAPI()

简单的速率限制

rate_limit_store = defaultdict(list)

RATE_LIMIT = 100 # 每分钟请求数

RATE_LIMIT_WINDOW = 60 # 秒

async def rate_limiter(request: Request):

client_ip = request.client.host

now = time.time()

# 清理过期记录

rate_limit_store[client_ip] = [

t for t in rate_limit_store[client_ip]

if now - t < RATE_LIMIT_WINDOW

]

if len(rate_limit_store[client_ip]) >= RATE_LIMIT:

raise HTTPException(

status_code=429,

detail="请求过于频繁"

)

rate_limit_store[client_ip].append(now)

@app.get("/api/data")

async def get_data(request: Request, limiter: bool = Depends(rate_limiter)):

return {"data": "success"}

七、实战案例

7.1 完整认证系统

from fastapi import FastAPI, Depends, HTTPException, status

from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm

from pydantic import BaseModel, EmailStr, Field

from passlib.context import CryptContext

import jwt

from datetime import datetime, timedelta

from typing import Optional

from sqlalchemy.orm import Session

from app.database import get_db

from app import models

app = FastAPI()

配置

SECRET_KEY = "your-secret-key"

ALGORITHM = "HS256"

ACCESS_TOKEN_EXPIRE_MINUTES = 30

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

模型

class UserCreate(BaseModel):

email: EmailStr

username: str = Field(..., min_length=3, max_length=50)

password: str = Field(..., min_length=8)

class UserLogin(BaseModel):

username: str

password: str

class Token(BaseModel):

access_token: str

token_type: str

refresh_token: Optional[str] = None

工具函数

def verify_password(plain_password: str, hashed_password: str) -> bool:

return pwd_context.verify(plain_password, hashed_password)

def get_password_hash(password: str) -> str:

return pwd_context.hash(password)

def create_access_token(data: dict) -> str:

to_encode = data.copy()

expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_EXPIRE_MINUTES)

to_encode.update({"exp": expire})

return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)

def create_refresh_token(data: dict) -> str:

to_encode = data.copy()

expire = datetime.utcnow() + timedelta(days=7)

to_encode.update({"exp": expire, "type": "refresh"})

return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)

def get_current_user(

token: str = Depends(oauth2_scheme),

db: Session = Depends(get_db)

):

credentials_exception = HTTPException(

status_code=status.HTTP_401_UNAUTHORIZED,

detail="Could not validate credentials",

headers={"WWW-Authenticate": "Bearer"},

)

try:

payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])

username: str = payload.get("sub")

if username is None:

raise credentials_exception

except jwt.ExpiredSignatureError:

raise credentials_exception

except jwt.InvalidTokenError:

raise credentials_exception

user = db.query(models.User).filter(models.User.username == username).first()

if user is None:

raise credentials_exception

return user

路由

@app.post("/register", response_model=Token)

async def register(user_in: UserCreate, db: Session = Depends(get_db)):

# 检查用户是否存在

existing_user = db.query(models.User).filter(

(models.User.username == user_in.username) |

(models.User.email == user_in.email)

).first()

if existing_user:

raise HTTPException(

status_code=status.HTTP_400_BAD_REQUEST,

detail="用户名或邮箱已存在"

)

# 创建用户

user = models.User(

username=user_in.username,

email=user_in.email,

hashed_password=get_password_hash(user_in.password)

)

db.add(user)

db.commit()

db.refresh(user)

# 生成令牌

access_token = create_access_token({"sub": user.username})

refresh_token = create_refresh_token({"sub": user.username})

return Token(access_token=access_token, token_type="bearer", refresh_token=refresh_token)

@app.post("/token", response_model=Token)

async def login(

form_data: OAuth2PasswordRequestForm = Depends(),

db: Session = Depends(get_db)

):

user = db.query(models.User).filter(models.User.username == form_data.username).first()

if not user or not verify_password(form_data.password, user.hashed_password):

raise HTTPException(

status_code=status.HTTP_401_UNAUTHORIZED,

detail="用户名或密码错误",

headers={"WWW-Authenticate": "Bearer"},

)

access_token = create_access_token({"sub": user.username})

refresh_token = create_refresh_token({"sub": user.username})

return Token(access_token=access_token, token_type="bearer", refresh_token=refresh_token)

@app.get("/users/me", response_model=models.User)

async def read_users_me(

current_user: models.User = Depends(get_current_user)

):

return current_user

@app.post("/token/refresh")

async def refresh_token(refresh_token: str):

try:

payload = jwt.decode(refresh_token, SECRET_KEY, algorithms=[ALGORITHM])

if payload.get("type") != "refresh":

raise HTTPException(status_code=401, detail="Invalid token type")

username = payload.get("sub")

if not username:

raise HTTPException(status_code=401, detail="Invalid token")

new_access_token = create_access_token({"sub": username})

new_refresh_token = create_refresh_token({"sub": username})

return Token(

access_token=new_access_token,

token_type="bearer",

refresh_token=new_refresh_token

)

except jwt.ExpiredSignatureError:

raise HTTPException(status_code=401, detail="Refresh token expired")

except jwt.InvalidTokenError:

raise HTTPException(status_code=401, detail="Invalid refresh token")

常见坑自查清单

现象自查方法修复方案
密钥泄露安全风险检查代码用环境变量
令牌永不过期安全风险检查exp设置过期时间
密码明文安全风险检查存储用bcrypt哈希
CORS错误跨域失败检查配置添加CORS中间件

结语

关键洞察

  • JWT适合无状态API认证
  • 密码必须哈希存储
  • 刷新令牌延长用户会话
  • 速率限制防止滥用

互动

  1. 1.你用JWT还是Session认证?
  2. 2.刷新令牌机制实现过吗?
  3. 3.遇到过认证相关的安全问题吗?
版本: V1.0 | 2026-05-26 | Python Web开发系列

📚 推荐阅读

📝 摘要:今天深入学习静态代码分析技术,这是安全审计的核心技能。从 Python AST 模块到检测模式设计,收获满满!

发布于 202603

01-Python 环境搭建与第一个脚本

发布于 202603

【优化】Python代码优化与调试技巧

发布于 202603

KEYWORDS

IL, Python, pip, 函数, 变量

💡 如果你觉得这篇文章有帮助,请点个在看,分享给更多需要的人!

📝 关注我,获取更多实用干货~

🤝 有问题欢迎评论区留言交流!

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-02 23:27:56 HTTP/2.0 GET : https://f.mffb.com.cn/a/498740.html
  2. 运行时间 : 0.148215s [ 吞吐率:6.75req/s ] 内存消耗:4,603.09kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=88db34553c6102714215438c20e0fbc2
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000488s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000619s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000281s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000760s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000483s ]
  6. SELECT * FROM `set` [ RunTime:0.013846s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000675s ]
  8. SELECT * FROM `article` WHERE `id` = 498740 LIMIT 1 [ RunTime:0.000805s ]
  9. UPDATE `article` SET `lasttime` = 1783006076 WHERE `id` = 498740 [ RunTime:0.036897s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.000407s ]
  11. SELECT * FROM `article` WHERE `id` < 498740 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000612s ]
  12. SELECT * FROM `article` WHERE `id` > 498740 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.009685s ]
  13. SELECT * FROM `article` WHERE `id` < 498740 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.007398s ]
  14. SELECT * FROM `article` WHERE `id` < 498740 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.008789s ]
  15. SELECT * FROM `article` WHERE `id` < 498740 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.000741s ]
0.149723s