如何使用会话限制对后端的访问,仅允许管理员在flask中访问后端? (蟒蛇)

时间:2018-10-24 17:24:01

标签: python flask

我想知道如何使用会话限制对网站某些页面的访问。在夏季,我希望管理员通过与普通用户相同的登录表单登录,但是使用他输入的凭据,他将被重定向到后端页面,在该页面他可以完全访问两个前端网页和后端网页。用户登录时,只能查看前端网页。我试图避免用户登录,然后将Web浏览器的搜索栏中的URL从127.0.0.7/homepage更改为127.0.0.7/backend,并由于他已登录而被允许访问的情况。

我正在使用下面的代码检查用户是否已登录。如果未登录,则将他们重定向到登录页面。我正在使用flask框架。任何建议都将不胜感激。

谢谢。

app.route('/backend', methods=['POST', 'GET'])
def backend():
if 'userkey' in session:
    # connect to database using pymysql
    if cursor.rowcount == 0:
        return render_template('backend.html', msg="No orders found...")
    else:
        rows = cursor.fetchall()
        return render_template('backend.html', orderdata=rows)

elif 'userkey' not in session:
    return redirect('/login')
else:
    return redirect('/login')

1 个答案:

答案 0 :(得分:0)

一旦用户通过身份验证,您必须已经在登录视图中设置了session ['userkey'],您只需要添加有关用户管理员状态的其他信息即可使此工作正常。如果将所有if 'userkey' in session检查从视图函数之外移到装饰器中,这样可以很容易地重用它来保护所有视图函数,那么会容易得多。该模式在烧瓶文档的“需要登录的装饰器” http://flask.pocoo.org/docs/1.0/patterns/viewdecorators/标题下显示。

在登录功能中,应在检索用户密钥和哈希密码的同时,在数据库中查询用户的管理员状态。然后,如果用户是管理员,则只需将session [“ admin”] = True设置为真;如果用户不是管理员,则根本不设置此设置。

下面的代码将对装饰器起作用。

from functools import wraps
from flask import session

def login_required(status=None):
    def login_decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            if 'userkey' in session and (status is None or status in session):
                return func(*args, **kwargs)
            else:
                return redirect("/login")
        return wrapper
    return login_decorator

然后应该应用此装饰器来保护您的所有视图功能。然后,它将在每个视图功能之前执行,如果所有条件都满足,则允许视图继续进行;如果不满足,则将用户重定向回登录页面。它具有可选的单个参数状态,在您的情况下,对于所有后端视图,该状态均应为“ admin”,而对于不需要管理员特权的前端视图,则不应提供该状态。函数内部的functools.wraps装饰器用于更新包装函数的元数据,以便使function.__name__之类的属性按预期运行。会话检查中的“用户密钥”与您原始代码中的“用户密钥”相同,但我们还会检查是否提供了状态,如果提供了状态,则是否也将其存储在会话中。在您的情况下,状态的唯一值是“ admin”,但是可以轻松扩展此模式,以允许其他每个组都可以访问网站的不同部分。

鉴于所有用户检查均在装饰器中进行,因此后端视图功能可以简化为

@app.route('/backend', methods=['POST', 'GET'])
@login_required("admin")
def backend():
    # connect to database using pymysql
    if cursor.rowcount == 0:
        return render_template('backend.html', msg="No orders found...")
    else:
        rows = cursor.fetchall()
    return render_template('backend.html', orderdata=rows)

可以使用相同的装饰器来保护所有前端视图功能,只需省略“ admin”参数即可。

@app.route('/frontend', methods=['POST', 'GET'])
@login_required()
def frontend():
    # .....