Flask Login异常:医师登录后短暂跳转回登录页问题
问题描述
系统包含医师(Physician)和患者(Patient)两类用户,患者登录功能正常,但医师登录成功跳转至医师仪表板后,页面仅短暂显示就自动重定向回登录页面。已参照患者登录逻辑修改医师登录的HTML及Python脚本,但问题仍未解决。
存在问题的医师登录相关代码
前端JS代码
document.getElementById('physicianLoginForm').addEventListener('submit', function(e) { e.preventDefault(); // Get the email and password from the form var email = document.getElementById('physician_username').value; var password = document.getElementById('physician_password').value; // Send the login data to the Flask backend fetch('/handle_physician_login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: email, password: password }) }) .then(response => response.json()) .then(data => { if (data.success) { // Redirect to the physician dashboard if login is successful window.location.href = data.redirect; } else { // Display error message if login failed document.getElementById('errorMessage').textContent = data.message; } }) .catch(error => console.error('Error:', error)); });
后端Python代码
class Physician(UserMixin): def __init__(self, id, email): self.id = id self.email = email @login_manager.user_loader def load_physician(user_email): conn = get_db_connection() if conn is None: return None try: cursor = conn.cursor() // Make sure to query the email column since user_email is an email cursor.execute("SELECT PhysicianId, WorkEmail FROM physicians WHERE WorkEmail=?", user_email) user_data = cursor.fetchone() if user_data: // Create the user object with the PhysicianId and Email return Physician(id=user_data.PhysicianId, email=user_data.WorkEmail) return None finally: conn.close() @app.route('/handle_physician_login', methods=['POST']) @limiter.limit("5 per minute") def handle_physician_login(): data = request.get_json() email = data['email'] password = data['password'] conn = get_db_connection() if conn is None: return jsonify({'success': False, 'message': 'Database connection failed'}), 500 try: cursor = conn.cursor() cursor.execute("EXEC AuthenticatePhysician @Email=?", email) physician = cursor.fetchone() if physician and check_password_hash(physician.Password, password): user = Physician(physician.PhysicianId, email) login_user(user) return jsonify({'success': True, 'redirect': url_for('physician_dashboard')}) else: return jsonify({'success': False, 'message': 'Invalid login credentials'}), 401 except Exception as e: return jsonify({'success': False, 'message': str(e)}), 500 finally: conn.close()
正常工作的患者登录相关代码
前端JS代码
<script> document.getElementById('patientLoginForm').addEventListener('submit', function(e) { e.preventDefault(); // Get the email and password from the form var email = document.getElementById('Email').value; var password = document.getElementById('Password').value; // Send the login data to the Flask backend fetch('/handle_patient_login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: email, password: password }) }) .then(response => response.json()) .then(data => { if (data.success) { // Redirect to the patient dashboard if login is successful window.location.href = data.redirect; } else { // Display error message if login failed document.getElementById('registrationMessage').textContent = data.message; } }) .catch(error => console.error('Error:', error)); }); </script>
后端Python代码
class Patient(UserMixin): def __init__(self, id, email): self.id = id self.email = email @login_manager.user_loader def load_user(user_email): conn = get_db_connection() if conn is None: return None try: cursor = conn.cursor() // Make sure to query the email column since user_email is an email cursor.execute("SELECT PatientID, Email FROM patients WHERE Email=?", user_email) user_data = cursor.fetchone() if user_data: // Create the user object with the PatientID and Email return Patient(id=user_data.PatientID, email=user_data.Email) return None finally: conn.close() @app.route('/handle_patient_login', methods=['POST']) @limiter.limit("5 per minute") def handle_patient_login(): data = request.get_json() email = data['email'] password = data['password'] conn = get_db_connection() if conn is None: return jsonify({'success': False, 'message': 'Database connection failed'}), 500 try: cursor = conn.cursor() cursor.execute("EXEC AuthenticatePatient @Email=?", email) patient = cursor.fetchone() if patient and check_password_hash(patient.Password, password): user = Patient(patient.PatientID, email) login_user(user) return jsonify({'success': True, 'redirect': url_for('patient_dashboard')}) else: return jsonify({'success': False, 'message': 'Invalid login credentials'}), 401 except Exception as e: return jsonify({'success': False, 'message': str(e)}), 500 finally: conn.close()
问题原因及解决方案
核心原因
Flask-Login 仅会使用一个被 @login_manager.user_loader 装饰的函数来加载登录用户。当前代码中,患者登录使用了 load_user 函数,而医师登录单独定义了 load_physician 函数,导致医师登录后,系统无法正确从 Session 中加载用户对象,仪表板路由检测到用户未登录,就会自动重定向回登录页。
解决步骤
合并用户加载逻辑
将医师和患者的加载逻辑合并到同一个load_user函数中,先尝试加载患者,若不存在则加载医师:@login_manager.user_loader def load_user(user_email): conn = get_db_connection() if conn is None: return None try: cursor = conn.cursor() # 先查患者表 cursor.execute("SELECT PatientID, Email FROM patients WHERE Email=?", user_email) user_data = cursor.fetchone() if user_data: return Patient(id=user_data.PatientID, email=user_data.Email) # 患者不存在则查医师表 cursor.execute("SELECT PhysicianId, WorkEmail FROM physicians WHERE WorkEmail=?", user_email) user_data = cursor.fetchone() if user_data: return Physician(id=user_data.PhysicianId, email=user_data.WorkEmail) return None finally: conn.close()同时删除原来的
load_physician函数。确认医师仪表板路由权限
确保医师仪表板的路由添加了@login_required装饰器,且没有额外的用户类型校验错误:@app.route('/physician_dashboard') @login_required def physician_dashboard(): # 仪表板逻辑 return render_template('physician_dashboard.html')验证用户对象的唯一性
确保Physician和Patient类的id属性不会出现重复(比如患者ID和医师ID使用不同的编号规则),避免加载用户时出现混淆。
内容的提问来源于stack exchange,提问作者37307554
相关产品推荐
相关产品推荐

