python - 处理登录 Flask Web 应用程序
问题描述
我目前正在构建我自己的第一个项目,一个带有 Flask 的 Web 应用程序,它与 Spotify API 交互。在本地和 Heroku 暂存环境中进行广泛测试后,该项目已经准备就绪。但是,我目前遇到了一个小的登录“错误”,我似乎无法理解。
单击登录按钮时,应用程序会向 Spotify API 发送请求,后者会在确认用户读取其数据后发回授权码。此确认将导致用户被重定向到 Web 应用程序的“/profile 路由”。到目前为止不同环境下的登录流程:
- 本地:进程一直运行顺利(阅读:单击登录按钮一次,将用户重定向到 /profile 路由)
- Staging (Heroku):单击登录按钮会生成对 Spotify API 的正确请求。但是,当我第一次单击它时,我被重定向到登录页面(由于我的 login_required Flask 装饰器)。当第二次单击它时,它还会生成正确的请求并将用户正确地发送到“/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 """
解决方案
不确定这是否是您的问题,但可能会导致一些奇怪的行为......
app.config['SECRET_KEY'] = os.urandom(64)
这将导致在每个 heroku dyno 上设置不同的密钥(如果运行多个工作程序;同步工作程序的默认值为 2),因为该随机字符串是在工作程序启动时动态生成的。
作为旁注,os.urandom
不是用于生成密钥。而是使用secrets
module,并将生成的字符串设置为 heroku CLI 中的配置变量,并将其加载到您的应用程序中:
import os
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY')
推荐阅读
- vba - 如何在VBA中将数组中的值移动n个单位
- ios - 如何在 Xcode 中的预编译头文件之前添加一个执行 shell 命令的步骤?
- asp.net-mvc - 将 Autofac 配置为与 ASP.NET MVC 和 ASP.NET Web Api 一起用于现有应用程序
- javascript - 为什么选择的选项隐藏在反应中?
- asterisk - 将日志文件放在多个目录中 Asterisk
- linux - 在 Yocto 中提取 Linux 源代码的命令
- java - 在 replaceAll 调用中修改正则表达式的一部分
- dialogflow-es - Actions SDK conv.hasScreen 未按预期工作
- typescript - switchMap,startWith,switchMap?
- react-native - 在类型的影子节点中更新属性“X”时反应本机错误:RCTView