按需Flask主要颗粒资源

2024-06-13 20:28:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在看这个帖子: http://pythonhosted.org/Flask-Principal/#granular-resource-protection

现在,虽然它的工作方式没有任何问题,但我看不出它是非常有用的,因为在登录时,所有的帖子都被读取,并且EditBlogPostNeed被添加到标识中。在

想象一下,如果我写的文章超过了正常数量,那么长期来看这不是一个很好的策略,因为我想在访问视图/posts/<post_id>时检查文章。在

有没有一种方法可以使用Flask Principal对视图的每个请求进行检查?在

当然,我可以很容易地用一个惰性关系查询和过滤器来绕过它,但是我想使用Flask Principal。在


Tags: org视图principalhttpflask方式文章resource
3条回答

虽然FlaskPrincipal是最流行的插件,但它没有必要复杂,在我需要的大多数情况下它都不能工作。我一直试图强迫它按我喜欢的方式工作,但我从来没有成功过。幸运的是,我找到了一个非常简单和轻量级的模块-permission

使用

首先,您需要通过子类化Rule来定义自己的规则,然后 重写check()deny()

# rules.py
from flask import session, flash, redirect, url_for
from permission import Rule

class UserRule(Rule):
    def check(self):
        """Check if there is a user signed in."""
        return 'user_id' in session

    def deny(self):
        """When no user signed in, redirect to signin page."""
        flash('Sign in first.')
        return redirect(url_for('signin'))

然后通过子类化Permission和重写rule()来定义权限:

^{pr2}$

有4种方法可以使用上面定义的UserPermission

1。用作视图装饰器

from .permissions import UserPermission

@app.route('/settings')
@UserPermission()
def settings():
    """User settings page, only accessable for sign-in user."""
    return render_template('settings.html')

2。在视图中使用代码

from .permissions import UserPermission

@app.route('/settions')
def settings():
    permission = UserPermission()
    if not permission.check()
        return permission.deny()
    return render_template('settings.html')

3。在视图中使用代码(使用with语句)

from .permissions import UserPermission

@app.route('/settions')
def settings():
    with UserPermission():
        return render_template('settings.html')

4。在Jinja2模板中使用

首先,您需要将定义的权限注入模板上下文:

from . import permissions

@app.context_processor
def inject_vars():
    return dict(
        permissions=permissions
    )

然后在模板中:

{% if permissions.UserPermission().check() %}
    <a href="{{ url_for('new') }}">New</a>
{% endif %}

我不确定我完全理解你的问题,但这可能会有帮助。在Flask应用程序中,我使用Flask Principal作为角色权限,比如admin和editor,我还使用它来进行粒度资源保护,如Flask-Principal docs中所述。在我的例子中,我检查用户是否有访问特定帐户的权限。在每个视图中,都会加载标识并检查权限。在

视图中

@login_required
def call_list(id, page=1):

    dept = models.Department.query.get_or_404(id)
    view_permission = auth.ViewAccountPermission(dept.office.account_id)

    if view_permission.can():
        # do something

自定义权限

^{pr2}$

标识加载器函数中

if hasattr(current_user, 'assigned_accounts'):
    for account_id in current_user.assigned_accounts():
        identity.provides.add(auth.ViewAccountNeed(unicode(account_id)))

我在这个话题上所能找到的一切似乎都过于迟钝。虽然不是我最初想要的,但我决定在视图函数中手动处理这个问题。它更显式,减少了对数据库的额外查询。请注意,我仍然使用flask-security作为其现成的基于角色的身份验证(这仍然是通过flask-principal通过其@roles_accepted('role')修饰符实现的)。在

@app.route('/my_accounts/', methods = ['GET'])
@app.route('/my_accounts/<int:id>/', methods = ['GET'])
@roles_accepted('client')
def my_accounts(id=None):

    if id:
        account = Account.query.get_or_404(id)

        if account.owner == current_user:
            return render_template("my_account.html",
                                   title = "Account: {0}".format(account.name),
                                   account = account)
        else:
            abort(403)

    accounts = Account.query.filter_by(owner=current_user).all()

    return render_template("my_accounts.html",
                           title = 'My Accounts',
                           accounts = accounts)

相关问题 更多 >