首页 > 解决方案 > 处理登录 Flask Web 应用程序

问题描述

我目前正在构建我自己的第一个项目,一个带有 Flask 的 Web 应用程序,它与 Spotify API 交互。在本地和 Heroku 暂存环境中进行广泛测试后,该项目已经准备就绪。但是,我目前遇到了一个小的登录“错误”,我似乎无法理解。

单击登录按钮时,应用程序会向 Spotify API 发送请求,后者会在确认用户读取其数据后发回授权码。此确认将导致用户被重定向到 Web 应用程序的“/profile 路由”。到目前为止不同环境下的登录流程:

我可以在服务器日志中看到第一次单击登录按钮会生成正确的请求。但似乎“/profile 路由”的 login_required 装饰器的验证“太快了”?还是这与缓存有关?因为我还能够通过删除缓存和硬刷新页面来重现错误(有时)。

我最近在会话中添加了一个 SECRET_KEY 并将 SESSION_PERMANENT 从 False 更改为 True 但我认为这不会导致问题?我认为一些代码可能会导致这个小错误:

# Ensure responses aren't cached
@app.after_request
def after_request(response):
    response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
    response.headers["Expires"] = 0
    response.headers["Pragma"] = "no-cache"
    return response


# Configure session to use filesystem
app.config['SECRET_KEY'] = os.urandom(64)
app.config["SESSION_FILE_DIR"] = mkdtemp()
app.config["SESSION_PERMANENT"] = True
app.config["SESSION_TYPE"] = "filesystem"
Session(app)
def login_required(f):
        """
        Decorate routes to require login:
        http://flask.pocoo.org/docs/1.0/patterns/viewdecorators/
        """
        @wraps(f)
        def decorated_function(*args, **kwargs):
            if session.get("authorization_header") is None:
                return redirect(url_for('login'))
            return f(*args, **kwargs)
        return decorated_function
@app.route("/")
    def index():
        """ Shows landing page """
        if session.get("authorization_header") is not None:
            return redirect(url_for('profile'))
    
        return render_template("index.html")
    
    
    @app.route("/login")
    def login():
        """ Shows login page """
        if session.get("authorization_header") is not None:
            return redirect(url_for('profile'))
    
        return render_template("login.html")
    
    
    @app.route("/logout")
    @helpers.login_required
    def logout():
        """ Logs user out """
        # Forget any user_id
        session.clear()
    
        # Redirect user to login form
        return redirect(url_for("index"))
    
    
    @app.route("/profile")
    @helpers.login_required
    def profile():
       """ Shows overview of user's Spotfy profile """

标签: pythonflaskflask-login

解决方案


不确定这是否是您的问题,但可能会导致一些奇怪的行为......

app.config['SECRET_KEY'] = os.urandom(64)这将导致在每个 heroku dyno 上设置不同的密钥(如果运行多个工作程序;同步工作程序的默认值为 2),因为该随机字符串是在工作程序启动时动态生成的。

作为旁注,os.urandom不是用于生成密钥。而是使用secretsmodule,并将生成的字符串设置为 heroku CLI 中的配置变量,并将其加载到您的应用程序中:

import os
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY')

推荐阅读