gpt4 book ai didi

python - Flask-Login @login-required 装饰器在 session 过期后不会重定向到登录页面

转载 作者:行者123 更新时间:2023-12-04 17:23:13 32 4
gpt4 key购买 nike

更新
下面的 Flask 重定向(响应代码 302)似乎作为对 _dash-update-component 的响应传递。要求:

b'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">\n<title>Redirecting...</title>\n<h1>Redirecting...</h1>\n<p>You should be redirected automatically to target URL: <a href="/login">/login</a>.  If not click the link.'
这解释了下面 dash_renderer 抛出的 SyntaxError,所以这导致我在 server.py 中添加以下内容:
@server.after_request
def check_response(response):

redirecting = 'Redirecting...' in response.get_data().decode('utf-8')
dash_response = request.path=='/_dash-update-component'

return make_response('', 204) if redirecting and dash_response else response
现在我可以模拟一个类似 Dash 的 PreventUpdate通过向破折号组件返回“204 No-Content”响应,但是我没有收到重定向回登录页面的额外请求。注释掉 after_request函数,然后跟踪 before_request 看到的请求,实际上表明 login()路由被调用并且 render_template('login.html')被返回,但它根本没有在浏览器中呈现......
以下原始帖子
过去几天,我大部分时间都在尝试修改我们的登录程序,以增加一些生活质量的更新和修改。出于这个问题的目的,我有兴趣在主 Dash 应用程序中一段时间​​不活动后注销我们的用户。
我的方法是为我们的登录页面注册路由,然后为 /dashapp 指向一个 Flask 路由。到 app.index() 返回的响应哪里 app指向 Dash 应用程序。一旦他们登录到 Dash 应用程序,我就有了一个 before_request将更新 session 修改属性和 session 过期时间的装饰器(出于测试目的,为 5 秒)。我也申请了 @login_required此调用函数的装饰器,以便 login_manager.unauthorized_handler如果用户在触发 before_request 时不再通过身份验证,则调用装饰者。我认为我的逻辑在这里是合理的,但我仍然遇到问题,我将在下面描述。
我可以登录我的用户并将他们重定向到主 Dash 应用程序 /dashapp ,我可以毫无问题地使用该应用程序。现在,当我等待 5 秒钟以允许 session 过期时,单击 Dash 应用程序中触发 dash 回调的组件会在控制台中产生以下错误:

dash_renderer.v1_7_0m1602118443.min.js:20 SyntaxError: Unexpected token < in JSON at position 0


我知道某些函数需要 JSON 响应,并且显然收到了 HTML 响应,但我无法确定那是什么。它还阻止我重定向回登录页面,当用户不再通过身份验证并触发 before_request 时,我希望调用该页面。装饰者。
我的代码结构如下(不是 config.py 只是我的 SQL 连接):
应用程序.py
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html

from server import app, server as application, User, login_manager
from flask_login import logout_user, current_user, login_user, login_required
from flask import session, redirect, render_template, url_for, request
from views import main

app.layout = html.Div([

dcc.Location(id='url', refresh=False),

html.Div(id='page-content')

])

@application.route('/login')
def login():

return render_template('login.html')

@application.route('/login', methods=['POST'])
def login_post():

if current_user.is_authenticated:

return redirect('/dashapp')

user = User.query.filter_by(username=request.form['username']).first()

#Check if user exists
if user:

#Check if password is correct
if user.password==request.form['password']:

login_user(user, remember=False)
return redirect('/dashapp')

@login_manager.unauthorized_handler
def unauthorized():

if request.path!='/login':
return redirect('/login')

@application.route('/logout')
@login_required
def logout():

logout_user()
return redirect('/login')

@application.route('/dashapp')
@login_required
def main_page():

return app.index()

@app.callback(
Output('page-content', 'children'),
[Input('url', 'pathname')])
def display_page(pathname):

if current_user.is_authenticated:
content = main.get_layout()
else:
content = dcc.Location(pathname='/login', id='redirect-id')

return content

if __name__ == '__main__':
app.run_server()
View /login.html
<html>
<head>
<title>Flask Intro - login page</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="static/bootstrap.min.css" rel="stylesheet" media="screen">
</head>
<body>
<div class="container">
<h1>Please login</h1>
<br>
<form action="" method="post">
<input type="text" placeholder="Username" name="username" value="{{
request.form.username }}">
<input type="password" placeholder="Password" name="password" value="{{
request.form.password }}">
<input class="btn btn-default" type="submit" value="Login">
</form>
{% if error %}
<p class="error"><strong>Error:</strong> {{ error }}
{% endif %}
</div>
</body>
</html>
server.py
import dash, os, datetime
from flask_login import LoginManager, UserMixin, current_user, login_required
from config import connection_string
import dash_bootstrap_components as dbc
from credentials import db, User as base
from flask import session, g, redirect, url_for, request, flash, render_template
import flask

external_stylesheets = [dbc.themes.BOOTSTRAP]

app_flask = flask.Flask(__name__)

app = dash.Dash(
__name__,
server=app_flask,
external_stylesheets=external_stylesheets,
update_title=None,
url_base_pathname='/'
)

app.title = 'Login Testing Interface'
server = app_flask
app.config.suppress_callback_exceptions = True

server.config.update(
SECRET_KEY=os.urandom(12),
SQLALCHEMY_DATABASE_URI=connection_string,
SQLALCHEMY_TRACK_MODIFICATIONS=False
)

db.init_app(server)

#Setup the LoginManager for the server
login_manager = LoginManager()
login_manager.init_app(server)
login_manager.login_view = 'login'

#Create User class with UserMixin
class User(UserMixin, base):

def get_id(self):

return self.user_id

#Reload the user object
@login_manager.user_loader
def load_user(user_id):

return User.query.get(user_id)

@server.before_request
@login_required
def check_authentication():

session.permanent = True
server.permanent_session_lifetime = datetime.timedelta(seconds=5)
session.modified = True
g.user = current_user
main.py
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc

from flask_login import current_user

from server import app, server

def get_layout():

return html.Div([

dcc.Location(id='url-main', refresh=False),

dbc.Button('Click me', id='test-click', n_clicks_timestamp=0),

html.Div(id='testing')

])

@app.callback(
Output('testing', 'children'),
[Input('test-click', 'n_clicks_timestamp')])
def update_test_div(clicks):

return f'Last clicked: {clicks}'
凭证.py
from flask_sqlalchemy import SQLAlchemy
from config import engine

db = SQLAlchemy()

db.Model.metadata.reflect(engine)

class User(db.Model):

__table__ = db.Model.metadata.tables['my_sql_table_with_user_details']
在此先感谢您的任何指导!

最佳答案

我建议将您的登录和登录后路由写成一个单一的功能

@app.route('/login', methods=['POST','GET'])
def login():
if current_user.is_authenticated :
return redirect('/')
if request.method == 'POST':
user_name = request.form.get('username')
password_entered =request.form.get('password')

present_user=User.query.filter_by(username=user_name).first()
if present_user.password == password_entered:
login_user(present_user)
next_page= request.args.get('next')
print(next_page)
return redirect(next_page) if next_page else redirect('/')
else:
flash('Incorrect Password',category='danger')
return render_template('user_login.html')
else:
return render_template('user_login.html')
如果您从 login_required 重定向登录页面的功能,
您可能会注意到顶部的链接/url 说
/login?next=%2FpathofFunction
当我们写

next_page= request.args.get('next')


我们在 ?next 之后得到剩余的 URL,然后将用户重定向到它来自的位置

关于python - Flask-Login @login-required 装饰器在 session 过期后不会重定向到登录页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64950129/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com