Flask视图函数在GET请求之后发送POST请求时丢失请求参数

时间:2020-07-02 16:33:15

标签: python http flask flask-login

在发出GET请求时,该视图将接收?next =参数,但是一旦用户向同一视图发出POST请求,该参数就会丢失。我见过的示例并未明确传递查询参数,但似乎能够保留它们并在以下POST请求中获取它们。

@blueprint.route("/login", methods=["GET", "POST"])
@logout_required()
def login():
    form = LoginForm()
    #1
    print("NEXT:", request.args.get("next"))

    if form.validate_on_submit():
        u = User.query.filter_by(username=form.username.data).first()
        if u and u.check_password(password=form.password.data):
            if u.is_active():
                #2
                print("NEXT:", request.args.get("next"))

                login_user(u, remember=form.remember.data)

                next_url = request.args.get("next")
                if not next_url or url_parse(next_url).netloc != "":
                    next_url = url_for("main.index")

                return redirect(next_url)
            else:
                flash("This account has been disabled", "error")
        else:
            flash("Invalid password or username.", "error")

    return render_template("auth/login.html", form=form)

2 个答案:

答案 0 :(得分:0)

在最后两个return redirect()函数之后,您缺少了两个flash()重定向,请参见下面的代码:

@blueprint.route("/login", methods=["GET", "POST"])
@logout_required()
def login():
    form = LoginForm()
    #1
    print("NEXT:", request.args.get("next"))

    if form.validate_on_submit():

        next_url = request.args.get("next")  #  -- HERE -- get "?next argument"

        u = User.query.filter_by(username=form.username.data).first()
        if u and u.check_password(password=form.password.data):
            if u.is_active():
                #2
                print("NEXT:", request.args.get("next"))

                login_user(u, remember=form.remember.data)

                # next_url = request.args.get("next")  # -- HERE -- 
                if not next_url or url_parse(next_url).netloc != "":
                    next_url = url_for("main.index")

                return redirect(next_url)

            else:
                flash("This account has been disabled", "error")
                return redirect(url_for('auth.index'))  # -- HERE --

        else:
            flash("Invalid password or username.", "error")
            return redirect(url_for('auth.login', next=next_url))  # -- HERE --

    return render_template("auth/login.html", form=form)

我假设/main是受保护的路由,并且当前没有会话,该用户尚未登录,因此,当用户尝试直接 访问时

http://localhost:5000/admin

他将自动重定向到此urlauth.login路由,并带有参数?next=%2Fadmin%2F

http://localhost:5000/auth/login?next=%2Fadmin%2F

使用默认的flask-login flash()消息Please log in to access this page.,然后他就可以登录,如果登录成功,他将登录并使用?next参数重定向到保护区,

但是如果发生并且诱惑失败,我们有两个选择:

  • 如果Invalid password or username会将他重定向到{strong> {strong> auth.login参数的?next=%2Fadmin%2F路线,则有第二次机会。

  • 但是如果This account has been disabled,他将被重定向到auth.login路由而没有 ?next=%2Fadmin%2F参数,这确实有意义。

最后,您不必担心?next=的值,因为用户可以使用它甚至删除它以及该块

                if not next_url or url_parse(next_url).netloc != "":
                    next_url = url_for("main.index")

                return redirect(next_url)

默认为main.index

答案 1 :(得分:0)

找出问题的根本原因是我将GET请求参数与POST输入提交混合在一起。

输入我的登录网址http://localhost:8000/auth/login?next=%2Fadmin

<form action="">

将向登录视图功能发送POST请求,并允许通过request.args.get()

进行访问

但是,捕获并传递GET请求next参数的正确方法是通过一个隐藏的输入字段,该字段包含初始GET请求的next参数,从而使其可以作为一部分正确传递POST请求中表格的形式。

<form action="{{ url_for('auth.login' }}">
    <input id="next" name="next" type="hidden" value="/admin">

查看功能:

@blueprint.route("/login", methods=["GET", "POST"])
@logout_required()
def login():
    form = LoginForm(next=request.args.get("next"))