'Flask login authentication fails on validate in production
I'm using flask-login to set up the log-in to a website and I have got it successfully working for when I run it in development via localhost. However, when I run my production website, it seems to fail on form.validate_on_submit() (returning false instead of true, and therefore skipping the login authentication steps) which seems very strange. Sometimes it is fixed if I clear my cache on my browser, but not always.
So far I have only set up the login process - I have manually added the information needed to my sqlalchemy users database as it is currently only running in production in a "beta" sense for a very limited set of users.
Below is the full authentication set up I am currently using. Any information on where I might be going wrong here would be very appreciated.
__init__.py - App set up
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from my_app.config import SECRET_KEY, SQLALCHEMY_BINDS, SQLALCHEMY_TRACK_MODIFICATIONS
def create_app(test_config=None):
'''
More complex and secure app initialisation.
More info from Flask Tutorial documentation: https://flask.palletsprojects.com/en/2.0.x/tutorial/
'''
app = Flask(__name__, instance_relative_config=True)
app.config['SQLALCHEMY_BINDS'] = SQLALCHEMY_BINDS
app.config['SECRET_KEY'] = SECRET_KEY
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = SQLALCHEMY_TRACK_MODIFICATIONS
db = SQLAlchemy()
db.init_app(app)
app.add_url_rule("/", endpoint="root")
return app
server.py - App routing
from flask import render_template, redirect, request, url_for, Flask
from flask_login import LoginManager, login_user, login_required, current_user
from werkzeug.security import generate_password_hash, check_password_hash
from my_app import create_app
from my_app.auth import User, login_form
app = create_app()
login_manager = LoginManager()
login_manager.init_app(app)
@login_manager.user_loader
def load_user(user_id):
return User.query.get(user_id)
@app.route('/login', methods=['GET', 'POST'])
def getLogin():
form = login_form()
if form.validate_on_submit():
try:
user = User.query.filter_by(name=form.username.data).first()
if check_password_hash(user.password, form.password.data):
login_user(user, remember=True)
return redirect('/home')
else:
return redirect('/login')
except Exception as e:
print(e)
return redirect('/login')
return render_template('login.html',
form=form,
text='Login',
btn_action='Login'
)
auth.py - User model and form definitions
import wtforms
import wtforms.validators as wtfv
from flask_login import UserMixin
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import FlaskForm
db = SQLAlchemy()
class User(UserMixin, db.Model):
__bind_key__ = 'users'
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(100), unique=True)
password = db.Column(db.String(100))
name = db.Column(db.String(100))
class login_form(FlaskForm):
username = wtforms.StringField(validators=[wtfv.InputRequired()])
# when in production, add length requirements to password field, using wtfv.Length(min='',max='')
password = wtforms.PasswordField(validators=[wtfv.InputRequired()])
Login.html - Login page
<!DOCTYPE html>
<html>
<head>
<title>
MASSAT Dashboard Login Page
</title>
<link rel="stylesheet" href='../static/stylesheets/modules/bootstrap.min.css'></link>
<link rel="stylesheet" href="../static/stylesheets/dashboardLayout.css"/></link>
</head>
<header class="header">
<div id="massat_acro" class="logo">
<a href="/">
<img src="/static/images/massat-logo.jpg" alt="MASSAT-Logo" height="45" padding="5px"/>
</a>
</div>
</header>
<body style="background-color:#fcfcfc; overflow-y: scroll;">
<div style="text-align:center;width:50%;margin:auto;padding:150px">
<div class="container">
<h2 style="color:black">Login to the MASSAT dashboard</h2>
<form action="{{ request.path }}" method="POST" class="card-body">
{{ form.csrf_token }}
<input class="form-control" id="username" name="username" placeholder="Username" required="" type="text" value="">
<input class="form-control" id="password" name="password" placeholder="Password" required="" type="password" value="">
<br>
<input class="btn btn-primary" type="submit" value='Login'>
</form>
</div>
</div>
</body>
</html>
Solution 1:[1]
You can try using the validator as; (Fields and Form instead of wtfv and FlaskForm)
from wtforms import Form, BooleanField, StringField, PasswordField, validators, TextAreaField
class login_form(Form):
name = StringField("Name", validators=[validators.Length(min=4, max=30)])
surname = StringField("Surname", validators=[validators.Length(min=4, max=30)])
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Furkan Y?ld?z |
