Flask中Jinja2的authenticated判断始终为False问题修复求助
问题描述
实现网站管理员页面时,输入正确凭证后跳转至http://127.0.0.1:5001/admin?authenticated=1,但页面仍显示“No Access”。相关代码如下:
app.py
@app.route('/login') def login(): return render_template('login.html', incorrect=False) @app.route('/login', methods=['POST']) def login_post(): creds = dict(request.form) if creds['username'] == USERNAME and creds['password'] == PASSWORD: return redirect(url_for('admin', authenticated=1)) else: return render_template('login.html', incorrect=True) @app.route('/admin') def admin(authenticated=0): conn = sqlite3.connect('articles.db') cur = conn.cursor() cur.execute("SELECT * FROM PENDING") articles = cur.fetchall() #print(articles) conn.close() return render_template('admin.html', authenticated=authenticated, articles=articles)
注:凭证均为admin(设置在.env文件中)
login.html
{% extends "base.html" %} {% block title %}Login{% endblock %} {% block content %} <div class="write container py-3 mx-auto bg-muted text-white" style="width: 60vw;"> <h1 action="{{ url_for('write_post') }}" data-aos="fade-up">Admin Login</h1> {% if incorrect %} <div class="alert alert-danger alert-dismissible"> <button type="button" class="btn-close" data-bs-dismiss="alert"></button> <strong>Incorrect Credentials</strong> Please try again. </div> {% endif %} <form method="POST" enctype=multipart/form-data> <label data-aos="fade-up" data-aos-delay="50" for="username">Username:</label><br> <input data-aos="fade-up" data-aos-delay="100" required maxlength="255" id="username" name="username"><br><br> <label data-aos="fade-up" data-aos-delay="150" for="password">Password:</label><br> <input data-aos="fade-up" data-aos-delay="200" required maxlength="255" id="password" name="password"><br><br> <input data-aos="fade-up" data-aos-delay="450" class="btn btn-success" type="submit"> </form> </div> {% endblock %}
admin.html
{% extends "base.html" %} {% block title %}Admin{% endblock %} {% block content %} {% if authenticated %} <div data-aos="fade-down" class=".container p-5 bg-muted text-white"> <h1>Articles pending review: </h1> </div> {% else %} <div data-aos="fade-down" class=".container p-5 bg-muted text-white"> <h1>No Access</h1> <p>You are not logged in!</p> </div> {% endif %} {% endblock %}
修复方案
问题根源
Flask路由函数的参数不会自动绑定URL查询参数(即?authenticated=1这类参数),当前admin函数的authenticated参数一直使用默认值0,所以模板中{% if authenticated %}始终为假。
另外,用URL参数传递认证状态存在安全隐患——任何人都可以直接修改URL参数获取权限,正确的做法是使用Flask的session存储登录状态。
具体修复步骤
导入并配置session
在app.py中导入session和os,设置加密用的SECRET_KEY(建议从.env文件读取,避免硬编码):from flask import session import os # 配置SECRET_KEY,用于session加密 app.secret_key = os.getenv('SECRET_KEY', 'temporary-dev-key')修改登录逻辑,用session存储认证状态
更新login_post函数,验证成功后将认证状态存入session,而非通过URL参数传递:@app.route('/login', methods=['POST']) def login_post(): creds = dict(request.form) if creds['username'] == USERNAME and creds['password'] == PASSWORD: session['authenticated'] = True # 存入session return redirect(url_for('admin')) else: return render_template('login.html', incorrect=True)修改admin路由,从session获取认证状态
更新admin函数,从session读取认证状态,未认证时直接返回无权限页面:@app.route('/admin') def admin(): # 从session获取认证状态,默认未认证 authenticated = session.get('authenticated', False) # 未认证时直接返回无权限页面 if not authenticated: return render_template('admin.html', authenticated=False) conn = sqlite3.connect('articles.db') cur = conn.cursor() cur.execute("SELECT * FROM PENDING") articles = cur.fetchall() conn.close() return render_template('admin.html', authenticated=authenticated, articles=articles)可选:添加退出登录功能
增加logout路由,清除session中的认证状态:@app.route('/admin/logout') def logout(): session.pop('authenticated', None) # 移除认证状态 return redirect(url_for('login'))
内容的提问来源于stack exchange,提问作者wenbang
相关产品推荐
相关产品推荐

