Vue js 和 Python flask API 架构

Vue js and Python flask API architecture

我是 vue 和 flask 的新手 api 计划使用 Vue js 前端和 flask api 来构建一个博客来操作日期。

我有一些架构问题。在 flask api 中,我可以基于使用登录创建令牌身份验证并将其共享 Vue 以供访问。但是在 flask api 中,我正在处理数据,例如删除博客 post、编辑 post 等。因此,如果终点暴露,请说 http://127.0.0.1:5000/deletePost 普通用户可以使用任何 post id 点击 api 并将其从数据库中删除。我该如何阻止呢?我只想对用户进行身份验证并保护管理员角色的数据操作。我还想使用 flask-login 当前用户来跟踪会话并显示相关的 post 和内容。

有什么建议的架构吗?

我不确定这是否是一个有效的问题。我只是想了解这里的架构。假设我在 mongo 数据库中有一个用户集合。因此,当用户使用有效的用户名和密码登录时,flask 将创建访问令牌,我会将其传递给 Vue 并存储在本地存储中。现在有一条路线说 delete post with post ID,我正在从数据库中删除 post。现在,如果 delete api 被暴露,一个有效的登录用户可以使用任何 post id 触发这个 delete api (注意我在 vue 模板中使用 post id 作为标识符)使用他们的访问令牌。它是如何保护它的?

由于您使用的是 flask-login,因此您可以创建自己的用户模型。 简单地继承自 UserMixin & db.Model。您可以在那里存储用户是否是管理员。

像这样:

from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class User(UserMixin, db.Model):
    """User account model."""

    __tablename__ = 'flasklogin-users'
    id = db.Column(
        db.Integer,
        primary_key=True
    )
    name = db.Column(
        db.String(100),
        nullable=False,
        unique=False
    )
    email = db.Column(
        db.String(40),
        unique=True,
        nullable=False
    )
    password = db.Column(
        db.String(200),
        primary_key=False,
        unique=False,
        nullable=False
    )
    is_admin = db.Column(
        db.Boolean(),
        primary_key=False,
        unique=False,
        nullable=False,
        default=False
    )

然后您使用 class 创建新用户,在登录时将他们添加到会话中并使用 class 的实例调用 login_user。 current_user 应该会给你访问这个用户的权限,你可以简单地检查 is_admin。如果任何人不是管理员,您只需 return 一个带有错误状态的响应。

如果您计划拥有 2 个以上的角色,您可以使用字符串列来代替,然后检查该角色。

如果这种情况经常发生,您可以创建一个装饰器来检查用户是否是管理员,并将其简单地放在您的行前面。

编辑: 我会做的是这样的:

@app.route('/deletepost/<post_id>', methods=['POST'])
@login_required
def delete_post():
    if not current_user.is_authenticated or not current_user.is_admin:        
        return Response(status=500)

如果这种情况经常发生,您可以将逻辑抽象成这样的装饰器:

def is_admin(fn):
    def decorate(*args, **kwargs):
        if not current_user.is_authenticated or not current_user.is_admin:        
            return Response(status=500)
        return fn(*args,**kwargs)

你可以像这样使用它:

@app.route('/deletepost/<post_id>', methods=['POST'])
@login_required
@is_admin
def delete_post():
    # do something