为什么 Flask 会话不存储模块之间的变量?

问题描述 投票:0回答:1

大家好,感谢您的时间和支持!

我目前正在我的身份验证模块中存储会话[“用户名”],然后尝试从后端应用程序(特别是从主端点)从我的项目模块访问它。问题是 session["username"] 从项目模块返回 None,我不知道为什么!!!

我尝试了不同的应用程序配置,ChatGPT 给了我一些建议,甚至创建了一个更简单的项目,其会话功能正常工作,没有问题,我复制了结构,但仍然存在相同的问题。

我做了一些研究,据说前端应用程序不应该成为问题,因为无论前面发生什么(React),后面的会话都应该保持不变。

app.py

from dotenv import load_dotenv
from flask import Flask
from flask_cors import CORS
from flask_session import Session
from models import db

load_dotenv('.env', override=True)

app = Flask(__name__)
app.config['SESSION_TYPE'] = 'filesystem'
app.config['SECRET_KEY'] = 'verysafekey'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db'
Session(app)
CORS(app, supports_credentials=True, origins=["http://localhost:3000"])
db.init_app(app)

from routes.auth import auth_bp
from routes.project import project_bp
from routes.jira import jira_bp
# Register blueprints
app.register_blueprint(auth_bp)
app.register_blueprint(project_bp)
app.register_blueprint(jira_bp)

if __name__ == '__main__':
    with app.app_context():
        db.create_all()
        app.run(debug=True, port=5000)

模型.py

import os
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base

# Initialize SQLAlchemy (deferred app initialization)
db = SQLAlchemy()

# Ensure the user_databases directory exists
if not os.path.exists('user_databases'):
    os.makedirs('user_databases')

# User model remains in the main database
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(50), unique=True, nullable=False)
    password = db.Column(db.String(100), nullable=False)

# Function to get the SQLAlchemy session for a user's database
def get_user_db_session(username):
    user_db_path = f"user_databases/{username}.db"
    user_engine = create_engine(f"sqlite:///{user_db_path}")
    session_factory = sessionmaker(bind=user_engine)
    return scoped_session(session_factory)

def create_user_db(username):
    user_db_path = f"user_databases/{username}.db"
    if not os.path.exists(user_db_path):
        user_engine = create_engine(f"sqlite:///{user_db_path}")
        Base.metadata.create_all(user_engine)

# Project and Issue models for the user-specific database
Base = declarative_base()

class Client(Base):
    __tablename__ = 'client'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    projects = db.relationship('Project', backref='client', lazy=True)

class Project(Base):
    __tablename__ = 'project'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    client_id = db.Column(db.Integer, db.ForeignKey('client.id'), nullable=False)
    issues = db.relationship('Issue', backref='project', lazy=True)

class Issue(Base):
    __tablename__ = 'issue'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    project_id = db.Column(db.Integer, db.ForeignKey('project.id'), nullable=False)
    content = db.Column(db.Text)

auth.py

@auth_bp.route('/login', methods=['POST'])
def login():
    data = request.get_json()
    username = data.get('username')
    password = data.get('password')
    
    session['username'] = username

    # Print debug info
    print("Session stored username for Login:")
    print(session.get("username"))

    # Simulate an external API call
    url = 'https://urchin-app-veelh.ondigitalocean.app/api/login'
    headers = {'Content-Type': 'application/json'}
    data = {"username": username, "password": password}
    new_response = requests.post(url, json=data, headers=headers)

    if new_response.status_code >= 200 and new_response.status_code <= 300:
        json_response = new_response.json()
        refresh_token = json_response.get('refreshToken')
        
        # Handle user database
        user = User.query.filter_by(username=username).first()
        if not user:
            create_user_db(username)
        
        return jsonify(success=True, user=username, token=refresh_token, message='Username and password match.')
    else:
        return jsonify(success=False, message='Incorrect username or password. Please try again.')

项目.py

@project_bp.route('/home', methods=['GET'])
def home_internal():
    print("Backend /home API reached")
    print("Session stored username for Home:")
    print(session.get("username"))
    
    username = session.get('username')
    if not username:
        return jsonify(success=False, message='Username not found in session.')

    user_db_session = get_user_db_session(username)
    clients = user_db_session.query(Client).all()
    projects = user_db_session.query(Project).all()

    has_clients = len(clients) > 0
    has_projects = len(projects) > 0

    return jsonify(success=True, has_clients=has_clients, has_projects=has_projects)

我尝试使用一个更简单的版本,没有前端来完成这个任务,有趣的是,它看起来与我的小项目相似;它仍然为会话中的用户名变量返回 None ;这是使用会话完美运行的虚拟对象。

app.py

from flask import Flask
from flask_session import Session

app = Flask(__name__)

# Configuration for the session
app.config['SECRET_KEY'] = 'supersecretkey'
app.config['SESSION_TYPE'] = 'filesystem'
Session(app)

# Registering blueprints (each blueprint corresponds to a module)
from create_session import create_session_bp
from print_session import print_session_bp
from print_session_again import print_session_again_bp

app.register_blueprint(create_session_bp)
app.register_blueprint(print_session_bp)
app.register_blueprint(print_session_again_bp)

if __name__ == '__main__':
    app.run(debug=True)

create_session.py

from flask import Blueprint, session

create_session_bp = Blueprint('create_session_bp', __name__)

@create_session_bp.route('/create_session')
def create_session():
    session['username'] = 'test_user'
    return "Session variable 'username' set to 'test_user'. <a href='/print_session'>Go to Print Session</a>"

print_session.py

from flask import Blueprint, session

print_session_bp = Blueprint('print_session_bp', __name__)

@print_session_bp.route('/print_session')
def print_session():
    username = session.get('username', 'Session variable not set!')
    return f"Session variable 'username' is: {username}. <a href='/print_session_again'>Go to Print Session Again</a>"

print_session_again.py

from flask import Blueprint, session

print_session_again_bp = Blueprint('print_session_again_bp', __name__)

@print_session_again_bp.route('/print_session_again')
def print_session_again():
    username = session.get('username', 'Session variable not set!')
    return f"Session variable 'username' is still: {username}."

flask session
1个回答
0
投票

我终于明白了!!

我没有包含来自前端的凭据,这最终意味着没有收到会话数据,因此;每次请求后我们都有空值!!

一个小的前后示例:

const response = await fetch('api/here');
const response = await fetch('api/here', {credentials: 'include'});
© www.soinside.com 2019 - 2024. All rights reserved.