Flask 会话不持久,在 SPA 中刷新页面时丢失数据

时间:2021-02-06 23:45:53

标签: javascript python reactjs flask socket.io

编辑:我意识到实际上甚至没有调用 else 语句,但在页面刷新时,它将 logged_in 值设置为 false。 else 语句中的打印永远不会打印。如果我不这样做,它是如何设置为 false 的?

我有一个由 Flask 服务的单页 React 应用程序,它们都在同一台服务器上。我使用 socket.io-client 在后端和前端之间进行通信。

登录后,前端加载用户数据就好了。如果我刷新页面,我将被注销并返回到登录页面。为什么会话不持久?

Flask 会话 cookie 存在于 Chrome 中。 session cookie id 与浏览器中的 session cookie 一致,刷新退出后,后台返回用户未登录。

会话 cookie 似乎在刷新时丢失了数据。

这是反应代码的片段:

const ENDPOINT = "http://127.0.0.3:5000";
const SocketContext = createContext(null);
const socket = io();

export function useIsLoggedIn() {
  const navigate = useNavigate();

  const [response, setResponse] = useState(data);

  useEffect(() => {
    socket.emit('join', setResponse);
  }, []);

  if (response.success) {
    console.log("routing to dashboard...");
    navigate("/app/dashboard");
  }

  return response;
}

export function useLogIn() {
  const sendMessage = (channel, message) => {
    socket.emit(channel, message);
  };

  return { sendMessage };
}

这是后端python代码的片段:


@socketio.on('join')
def on_connect(data):
    try:
        if 'logged_in' in session and session['logged_in']:
            print('logged_in')
            user_content = content.get_content(user=session['username'])
            error = None
            join_room(session['company'])
            emit('sign_in', {'content': user_content, 'error': error, 'success': True}, room=session['company'])
        else:
            print('not_logged_in')
            error = 'Invalid login credentials'
            emit('sign_in', {'content': CONTENT, 'error': error, 'success': False})
    except Exception as e:
        print(traceback.format_exc())
        # print(e)

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def catch_all(path):
    print('path', path)
    try:
        print('session logged_in', session['logged_in'])
    except Exception as e:
        print('failed not logged_in', e)
    if 'logged_in' not in session:
        print('set logged_in to False')
        session['logged_in'] = False
        session.permanent = True
    resp = make_response(render_template('index.html'))
    return resp

数周以来,我一直试图弄清楚为什么会话会重置并在刷新时将用户注销。感谢您提供任何帮助,谢谢。

1 个答案:

答案 0 :(得分:1)

如果你需要使用 Flask,你应该尝试使用 Flask 库来处理登录状态,在这种情况下,flask_login。

我不会在此提供所有详细信息,但我相信您至少需要以下内容才能使其正常工作:

在您的应用定义文件中:

from flask import Flask
from flask_login import LoginManager


login_manager = LoginManager()


def create_app():
    """App factory."""
    app = Flask(__name__, instance_relative_config=True)

    login_manager.init_app(app)
    with app.app_context():

        from my_app.views.view_users import view_users
        from my_app.views.main_view import main_view
        app.register_blueprint(view_users)
        app.register_blueprint(main_view)

        # Login manager config
        login_manager.login_view = 'view_users.login'

接下来,您需要创建 view_users.py。此文件应包含来自 flask_login 包的 login_user。

from flask import render_template, Blueprint, redirect, url_for
from flask_login import login_user

view_users = Blueprint('view_users', __name__)


@view_users.route('/login', methods=['GET', 'POST'])
def login():
    """Login the user."""

    if password_matches(pass_db, passw):  # you need to check the provided password - you will need a form and a html for it
        login_user(user)

        next = url_for('main_view.landing')
        return redirect(next)

当然,你仍然需要为@login_manager.user_loader 和继承自flask_login.UserMixin 的User 类定义一个函数。请检查文档。

最后,在您的视图/路由/端点定义文件中,使用@login_required 装饰每个路由定义:

from flask_login import login_user, login_required, logout_user, current_user
from flask import render_template, Blueprint

main_view = Blueprint('main_view', __name__)


@main_view.route('/landing')
@login_required
def landing():
    """Landing page after user login."""
    data = ['my data']
    user_details = current_user  # if you need any - this will come from your user_loader function
    return render_template(
            'landing.html',
            data=data
        )


@main_view.route('/a_end_point')
@login_required
def a_end_point():
    """Landing page after user login."""
    user_details = current_user  # if you need any - this will come from your user_loader function
    data = ['my data']
    return render_template(
            'a_end_point.html',
            data=data
        )

祝你好运!

相关问题