python - 通过链接装饰器使用 Flask-HTTPAuth 创建特权用户 --- 丢失上下文?

标签 python flask basic-authentication python-decorators flask-httpauth

我正在尝试使用 Flask-HTTPAuth 创建一个具有基本身份验证的两层身份验证系统。我的应用程序有两个路由,一个位于 / 的基本路由可供任何登录用户访问,另一个位于 /admin 的管理路由仅可供以下用户访问(正如您所期望的) )以管理员身份登录。

因此,我决定通过链接装饰器来实现这一点,相关代码部分如下(其中 dbops 只是处理与数据库通信的 namespace ):

@auth.verify_password
def verify_pw(lastname, password):
    ln = lastname.lower()
    if ln in dbops.list_users():
        hashed_pw = dbops.find_hashed_password(ln)
        return bcrypt.checkpw(password.encode('utf8'), hashed_pw.encode('utf8'))
    return False

def must_be_admin(f):
    @wraps(f)
    def wrapper(*args, **kwargs):
        if dbops.is_admin(auth.username()):
            return f(*args, **kwargs)
        return "Not authorized."
    return wrapper

@core.route("/")
@auth.login_required
def dataentry():
    return render_template("dataentry.html")

@core.route("/admin")
@must_be_admin
@auth.login_required
def admin():
    return render_template("admin.html")

只要任何尝试以管理员用户身份登录的人首先访问 / 路由,就可以正常工作:它会提示输入用户名和密码,然后管理员用户可以转到 /admin 并执行登录的管理任务。

但是,如果管理员用户首次访问 /admin,它不会给出登录提示。它只是抛出,在调试器中查看后,我确定 auth.username() 返回一个空字符串。所以,我的猜测是,由于某种原因,内部装饰器没有被应用,因此缺少登录提示。

有人知道这里会发生什么吗?

我的第一个假设是,这是一个简单的错误,因为管理装饰器上的内部函数直到 is_admin 检查之后才被调用。因此,我尝试在检查之前修复我调用该函数的问题,从而大概使 auth.username() 可用,如下所示:

def must_be_admin(f):
    @wraps(f)
    def wrapper(*args, **kwargs):
        dummy_to_get_username = f(*args, **kwargs)
        if dbops.is_admin(auth.username()):
            return dummy_to_get_username
        return "Not authorized."
    return wrapper

但这只会导致相同的行为。

我从this prior SO看到库作者推荐的方法是创建两个单独的 Flask-HTTPAuth 对象。我能做到,没问题。但显然我关于装饰器如何工作的心理模型失败了,所以我想解决这个问题,而与获得我想要的功能无关......

最佳答案

如果不知道装饰器的作用,有时很难弄清楚应用装饰器的正确顺序,但不幸的是,错误的顺序会导致应用程序行为不正确。

对于在 View 函数运行“之前”执行某些操作的装饰器(如本例所示),您通常必须按照您希望它们执行的顺序放置装饰器。因此,我认为当您在 must_be_admin 之前使用 Flask-HTTPAuth 的 login_required 时,您的代码将达到您的预期:

@core.route("/admin")
@auth.login_required
@must_be_admin
def admin():
    return render_template("admin.html")

这样,将首先检查凭据,如果缺少或无效 login_required 将向浏览器返回 401 错误,从而出现登录提示。只有在确定凭据有效后,您才需要评估管理装饰器。

关于python - 通过链接装饰器使用 Flask-HTTPAuth 创建特权用户 --- 丢失上下文?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47836728/

相关文章:

python - 有一个 "this should never happen"声明是好的做法吗

python - 将 .csv 文件读取到 pandas 数据框并从换行符中识别数据部分

python - 如何覆盖 Flask 配置中的配置参数?

python - 如何直接访问SQLite数据库删除alembic_version表?

nginx 基本身份验证不适用于 Windows

python - 如何在python的派生类中调用同名方法的基类方法?

python - 如何使用 3 个列表创建字典的字典?

flask - SQLAlchemy 多对多关系更新具有额外列的关联对象

java - 将 Http 基本身份验证添加到 servletRequest

javascript - 使用 Javascript 验证 Windows 身份验证