You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask应用中如何安全获取数据库存储的Tokens与Keys?

问题描述

我开发了一个基于Flask和PostgreSQL的应用,企业的Tokens与Keys存储在companies表中,需要在应用的多个位置调用这些凭证。请问正确的实现方式是什么?是否有懒加载方案?

目前我尝试使用app.config(但不确定app_context或before_first_request的用法),示例代码如下:

with app.app_context():
    if current_user:
        app.config["CURRENT_COMPANY_ID"] = current_user.company_id
        app.config["YANDEX_TOKEN"]  =Company.query.filter_by(id=current_user.company_id).one().yandex_disk_token

或者使用g对象:

with app.app_context():
    if current_user:
        g.company_id = current_user.company_id
        g.yandex_token  =Company.query.filter_by(id=current_user.company_id).one().yandex_disk_token

但这些方法时常出现current_user为None或Company为None的错误,我不清楚该如何存储和获取这些Tokens与Keys,以确保仅登录用户可访问?


正确实现方案

1. 核心原则:禁用app.config存储用户/企业专属凭证

app.config是全局共享的配置容器,所有请求都会共用其中的内容。如果在这里存储某个用户的企业凭证,会导致并发请求时数据串用,完全不符合需求。必须使用请求级别的上下文对象g,它的生命周期和单个请求绑定,每个请求都有独立的g实例。

2. 结合请求钩子+登录验证加载凭证

使用Flask的before_request钩子,在每个请求处理前自动加载当前登录用户的企业凭证,同时必须先验证用户登录状态:

from flask import g, current_user
from flask_login import login_required
from your_app.models import Company

@app.before_request
def load_company_credentials():
    # 初始化凭证为None,避免后续调用时出现属性不存在的错误
    g.company_id = None
    g.yandex_token = None

    # 仅对已登录用户加载凭证
    if current_user.is_authenticated:
        try:
            # 通过用户关联的企业ID查询企业,用get()避免查询不到时抛出异常
            company = Company.query.get(current_user.company_id)
            if company:
                g.company_id = current_user.company_id
                g.yandex_token = company.yandex_disk_token
        except Exception as e:
            # 可添加日志记录异常,比如logging.error(f"加载企业凭证失败: {str(e)}")
            pass

同时,在所有需要使用凭证的路由上添加@login_required装饰器,确保只有登录用户能访问:

@app.route('/use-yandex-api')
@login_required
def use_yandex_api():
    if not g.yandex_token:
        return "无法获取有效企业凭证", 403
    # 调用Yandex API的逻辑
    return "API调用成功"

3. 懒加载实现:按需查询数据库

如果不是所有请求都需要用到凭证,可以用懒加载的方式,只在需要时才查询数据库,减少不必要的DB请求:

from flask import g, current_user
from your_app.models import Company

def get_yandex_token():
    # 检查g中是否已缓存凭证,没有则查询
    if not hasattr(g, 'yandex_token') or g.yandex_token is None:
        g.yandex_token = None
        if current_user.is_authenticated:
            company = Company.query.get(current_user.company_id)
            if company:
                g.yandex_token = company.yandex_disk_token
    return g.yandex_token

# 使用示例
@app.route('/use-yandex-api')
@login_required
def use_yandex_api():
    token = get_yandex_token()
    if not token:
        return "无法获取有效企业凭证", 403
    # 后续逻辑

4. 错误原因解析

  • current_user为None:你之前的代码用with app.app_context()手动创建上下文,但这只是应用上下文,没有请求上下文,current_user在非请求上下文中是无效的。必须在请求钩子或路由处理函数中操作,这些地方天然带有请求上下文,current_user才会正确指向当前登录用户(或匿名用户)。
  • Company为None:直接用.one()查询企业,当不存在时会抛出异常,应该用.get()方法,查询不到时返回None,再做判断;另外要确保current_user.company_id是有效的(比如用户表和企业表的外键约束要正确)。

内容的提问来源于stack exchange,提问作者Константин Прудников

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 15:31:58