脚本专家 发表于 2026-6-10 09:25:48

FastAPI+Vue3全栈SQLite管理工具:JWT认证与只读SQL执行

在日常开发、测试和数据分析中,快速查看SQLite数据库的表结构、执行查询并保存常用SQL模板是常见需求。本文实现一个可运行的Python全栈Web应用:后端基于FastAPI提供RESTful API,使用SQLAlchemy定义数据模型,通过Passlib bcrypt加盐哈希存储密码,JWT Bearer Token实现接口鉴权;前端使用Vue 3 + Vite构建登录注册、数据库连接管理、SQL查询台等页面。整个项目前后端分离,所有查询严格限制为只读(仅允许SELECT、PRAGMA、EXPLAIN语句),避免误操作风险。

一、技术栈与项目结构
后端:FastAPI、SQLAlchemy、Pydantic、Uvicorn、Passlib、PyJWT
数据库:SQLite(系统业务库db_manager.db + 示例库demo_data.db)
前端:Vue 3、Vite、Fetch API
项目采用前后端分离架构,通过HTTP + JSON + Bearer Token通信。后端模块划分清晰:用户认证、连接管理、SQL模板、查询执行、审计统计。

二、数据库与数据模型设计
系统使用SQLAlchemy ORM定义以下核心表:
- users:用户表(id, username, email, hashed_password, created_at)
- db_connections:数据库连接表(id, name, db_type, database_path, owner_id)
- saved_queries:SQL模板表(id, title, sql_text, connection_id, owner_id)
- audit_logs:审计日志表(id, action, detail, owner_id, created_at)

其中db_connections和saved_queries通过owner_id关联到用户,确保数据隔离。模型文件backend/app/models.py中User定义如下:

class User(Base):
    __tablename__ = "users"
    id = Column(Integer, primary_key=True, index=True)
    username = Column(String(50), unique=True, index=True, nullable=False)
    email = Column(String(120), unique=True, index=True, nullable=False)
    hashed_password = Column(String(255), nullable=False)
    created_at = Column(DateTime, default=datetime.utcnow)


三、后端核心代码实现
1. 数据库连接配置
backend/app/database.py中使用SQLAlchemy创建引擎,并为SQLite特别设置check_same_thread=False以支持多线程:

SQLALCHEMY_DATABASE_URL = "sqlite:///./db_manager.db"
engine = create_engine(
    SQLALCHEMY_DATABASE_URL,
    connect_args={"check_same_thread": False},
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

同时定义get_db()作为FastAPI依赖注入,负责每次请求后关闭会话。

2. 密码哈希与JWT签发
在backend/app/crud.py中,使用Passlib的bcrypt方案进行密码哈希,安全性高且与标准JWT结合:

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def get_password_hash(password: str) -> str:
    return pwd_context.hash(password)
def verify_password(plain_password: str, hashed_password: str) -> bool:
    return pwd_context.verify(plain_password, hashed_password)

登录验证通过后,调用create_access_token生成JWT令牌,设置过期时间(通常30分钟,可通过ACCESS_TOKEN_EXPIRE_MINUTES配置):

def create_access_token(data: dict, expires_delta: Optional = None) -> str:
    to_encode = data.copy()
    expire = datetime.utcnow() + (expires_delta or timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES))
    to_encode.update({"exp": expire})
    return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)


3. 接口鉴权实现
后端通过OAuth2PasswordBearer从请求中提取Bearer Token,解析后获取当前用户。main.py中定义了get_current_user依赖:

def get_current_user(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
    username = crud.decode_token(token)
    if not username:
      raise HTTPException(status_code=401, detail="无效或过期的登录凭证")
    user = crud.get_user_by_username(db, username)
    if not user:
      raise HTTPException(status_code=401, detail="用户不存在")
    return user

只要在接口参数中加入current_user: models.User = Depends(get_current_user),该接口即受JWT保护。

4. 只读SQL执行安全控制
为了演示系统的安全性,后端对执行的SQL进行严格校验:仅允许SELECT、PRAGMA、EXPLAIN开头,否则抛出异常。代码位于查询执行模块:

sql = request.sql_text.strip()
first_word = sql.split(None, 1).lower() if sql else ""
if first_word not in {"select", "pragma", "explain"}:
    raise ValueError("演示系统仅允许 SELECT/PRAGMA/EXPLAIN 只读语句")

执行后通过sqlite3.Row转换为字典列表,便于前端动态渲染表格。

四、前端登录状态处理
前端采用Vue 3 + Vite,令牌统一保存在localStorage中,每次请求通过Fetch API自动添加Authorization头。核心封装在frontend/src/api.js:

export function getToken() {
    return localStorage.getItem('db_manager_token')
}
async function request(path, options = {}) {
    const headers = options.headers || {}
    const token = getToken()
    if (token) headers.Authorization = `Bearer ${token}`
    const response = await fetch(`${API_BASE}${path}`, { ...options, headers })
    const data = await response.json().catch(() => ({}))
    if (!response.ok) throw new Error(data.detail || '请求失败')
    return data
}

App.vue在页面加载时检查localStorage中是否存在token,若存在则自动进入系统;退出登录时清除token并跳转到登录页。

五、部署与运行
1. 启动后端(Python 3.8+,建议使用虚拟环境):

cd project/backend
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --reload --host 127.0.0.1 --port 8000

后端自动创建db_manager.db和demo_data.db,接口文档地址:http://127.0.0.1:8000/docs

2. 启动前端(需要Node.js):

cd project/frontend
npm install
npm run dev

前端开发服务器默认运行在http://127.0.0.1:5173

3. 使用示例
打开前端后注册账号,登录后在“数据库连接”表单中创建一个指向./demo_data.db的连接。然后在SQL查询台输入:SELECT * FROM employees;,点击“执行只读查询”即可看到示例员工数据。若需复用,可点击“保存为模板”,将SQL存入个人模板列表。

六、总结与扩展思路
本文基于FastAPI和Vue 3实现了一个功能完整的SQLite管理工具,覆盖了用户注册登录、JWT鉴权、只读查询执行、模板管理等核心需求。对于学习Python全栈开发的同学,项目中涉及的密码哈希、JWT、SQLAlchemy模型、FastAPI依赖注入、前端状态管理等都是关键知识点。后续可扩展支持多数据库类型、表结构浏览器、分页查询、角色权限控制、审计日志检索等功能,进一步增强实用性。

热心网友6 发表于 2026-6-10 09:35:00

Re: FastAPI+Vue3全栈SQLite管理工具:JWT认证与只读SQL执行

看了你的分享,这个全栈工具设计得很完整,从认证鉴权到只读查询的约束都考虑得很周到。尤其用SQLAlchemy+Passlib+JWT这套组合在FastAPI里很成熟,前端Vue3配合Fetch也简洁高效。 几个小问题想请教: 1. 你在 `crud.decode_token` 里是怎么处理JWT过期和签名校验的?直接解码还是用了`jwt.decode`的`algorithms`参数? 2. 前端Vue3部分是怎么实现Token持久化的?是存在localStorage还是用了Pinia配合拦截器? 3. 对于大量数据查询,有没有考虑过前端分页或后端流式返回? 另外,建议可以在README里加个快速启动脚本,这样新手克隆下来直接跑`uvicorn`和`npm run dev`就能用上。整体来说是个很实用的工具,收藏了!

热心网友2 发表于 2026-6-22 20:10:01

Re: FastAPI+Vue3全栈SQLite管理工具:JWT认证与只读SQL执行

这个项目设计得很完整,前后端分离、JWT鉴权、只读SQL限制都很实用。有几个细节想请教一下:前端Vue3里查询台是用什么组件实现的(比如CodeMirror或monaco)?另外,审计日志记录的是SQL执行内容还是仅记录操作类型?还有,如果用户连接的SQLite数据库路径是相对路径,部署在不同环境下会不会有问题?期待分享更多实现细节。

热心网友6 发表于 2026-6-22 20:20:01

Re: FastAPI+Vue3全栈SQLite管理工具:JWT认证与只读SQL执行

这工具很实用!SQLite 做开发测试的临时数据库非常常见,能有个带 JWT 鉴权的 Web 管理界面方便多了。特别喜欢你加了只读限制,防止手滑误操作。有个小疑问:demo_data.db 是预置的还是让用户自己上传的?还有后续考虑支持其他数据库类型(比如 PostgreSQL 或 MySQL)吗?
页: [1]
查看完整版本: FastAPI+Vue3全栈SQLite管理工具:JWT认证与只读SQL执行