Hi I was implementing a login verification to restrict certain routes on a website. Users are created successfully and if a user does not exist, they cannot log in. However, when attempting to access a route that requires a login, changing the username still allows access to the route. Do you know why this might be happening?
This is the code:
from flask import Flask, redirect, flash, request, render_template, url_for, make_response
import secrets
from flask_login import login_required, LoginManager, login_user, UserMixin
from flask_sqlalchemy import SQLAlchemy
app = Flask("test")
secret_key = secrets.token_hex(16)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
app.config['SECRET_KEY'] = secret_key
db = SQLAlchemy(app)
login_manager = LoginManager(app)
login_manager.init_app(app)
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), unique=True, nullable=False)
password = db.Column(db.String(120), nullable=False)
email = db.Column(db.String(100), unique=True, nullable=False)
games = db.relationship('Game', backref='user', lazy=True)
class Game(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
moves= db.Column(db.String(500), nullable=False)
status = db.Column(db.String(5), nullable=False)#Si o no
color = db.Column(db.String(20), nullable=False)
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
@login_manager.unauthorized_handler
def unauthorized():
return redirect(url_for("login"))
@app.route('/')
def home():
return render_template('begin.html')
@app.route('/login',methods=['GET','POST'])
def login():
if request.method == 'POST':
name= request.form['user']
psw = request.form['psw']
user = User.query.filter_by(name=name).first()
if user and user.password==psw:
login_user(user)
route = '/'+str(user.name)+'/home'
return redirect(route)
else:
return render_template('login.html',resultado='user not found')
else:
return render_template('login.html')
@app.route('/registrar',methods=['GET','POST'])
def registrar():
if request.method == 'POST':
user = request.form['user']
email = request.form['email']
psw = request.form['psw']
confirm_psw = request.form['confirm_psw']
if psw != confirm_psw:
return render_template('registrar.html',validacion="Passwords do not match")
new_user = User(name=name, email=email, password=psw)
db.session.add(new_user)
db.session.commit()
return redirect('/login')
else:
return render_template('registrar.html')
@app.route('/<user>/home',methods=['GET','POST'])
@login_required
def main_page(user):
return render_template('home.html',user=user)
UPDATE
After some research I know the problem is with the url in the main_page. When I change the user in the url the current_user doesn't change so the current_user is the user that make login and the login_required doesn't look for the new user. I don't know if I am correct because I tried to fixed it but it doesn't work
The first thing to underestand is that your logged in user is being loaded every time they go to a route, and we define this behaviour in this seccion of code:
Whats happening here is that we are loading the user using it's
user_idwhich is stored in flask'ssessionobject, as you can see in this line of codeUser.query.get(int(user_id))So the reazon it doesn't prompt the user to login again is because the
user_idhasn't changed even when theusernamewas changed.What you could do if you want that to happen is to clear the session when you change the username, like this: