I am trying to build a simple web app, which has a form to change one's password. I am using werkzeug.security functions (check_password_hash and generate_password_hash) to do so. This two functions work perfectly in during registering and logging in. But for some reason, when I change password, the password just doesn't match. I even wrote a code to check the password right away, passwordChange = check_password_hash(newHash, newPassword), then print(f'\n\n{passwordChange}\n\n')but for some reason it always returned false. Here is the full code. Any response is greatly appreciated :)
FLASK
#app.route("/passwordchange", methods=["GET", "POST"])
#login_required
def changepassword():
""""Change users' password"""
if request.method == "POST":
newPassword = request.form.get("newPassword")
newConfirmation = request.form.get("newConfirmation")
# Ensure that the user has inputted
if (not newPassword) or (not newConfirmation):
return apology("Please fill all of the provided fields!", 400)
# Check to see if password confirmation were the same or not
if newPassword != newConfirmation:
return apology("password did not match with password (again)", 400)
user_id = session["user_id"]
newHash = generate_password_hash("newPassword")
db.execute("UPDATE users SET hash = ? WHERE id = ?", newHash, user_id)
passwordChange = check_password_hash(newHash, newPassword)
print(f'\n\n{passwordChange}\n\n')
return redirect("/login")
else:
return render_template("password.html")
HTML
{% extends "layout.html" %}
{% block title %}
Change Password
{% endblock %}
{% block main %}
<form action="/passwordchange" method="post">
<div class="form-group">
<input class="form-control" name="newPassword" placeholder="New Password" type="password">
</div>
<div class="form-group">
<input class="form-control" name="newConfirmation" placeholder="New Password (again)" type="password">
</div>
<button class="btn btn-primary" type="submit">Change Password</button>
</form>
{% endblock %}
Related
My project requires I read and write input username and password to a text file (not db or json). From there when the user logs in, I need to verify that the username and password match. I have encrypted the password using sha256. Every time I attempt to login with a known username and password, it fails to find the user and flashes "Incorrect data. Please try again."
This is my Python Code:
#app.route('/LoginSuccess/', methods=['GET', 'POST'])
def login_success():
username = request.form.get("username")
password = request.form.get("password")
for line in open('users.txt', 'r').readlines():
login_info = line.split(',')
hashpass = login_info[2]
flash('Verifying inputs....')
if username == login_info[0]:
flash('Username correct')
if sha256_crypt.verify(password, hashpass):
flash('You are logged in!')
return render_template('index.html')
else:
flash('Incorrect data. Please try again.')
return render_template('login.html', username=username, password=password)
This is my HTML code:
{% extends "dashboard.html" %}
{% block body %}
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class="flashes">
{% for message in messages %}
<div class="message_flash">{{ message }}</div>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
<h1>Login</h1>
<form action="/LoginSuccess/" method="POST">
<div>
<label for="username">Username</label>
<input type="text" class="form-control" name="username" placeholder="Username" required>
</div>
<div>
<label for="password">Password</label>
<input type="password" class="form-control" name="password" placeholder="Password" required>
</div>
<div class="submit">
<button type="submit" class="btn btn-default">Log In</button>
</div>
</form>
{% endblock %}
As #John Gordon commented, your code will render your login page (i.e. treat it as a failed login) if the first line (and only the first line) of your users.txt file does not match the credentials given. Instead you need to check the entire file before coming to that conclusion. So you need all of your iterations (through the users.txt file) to complete before executing the render login page if there were no matches. Basically, this means removing the else keyword and moving the last two lines of your code outside of the for block of code. e.g.
for line in open('users.txt', 'r').readlines():
login_info = line.split(',')
hashpass = login_info[2]
flash('Verifying inputs....')
if username == login_info[0]:
flash('Username correct')
if sha256_crypt.verify(password, hashpass):
flash('You are logged in!')
return render_template('index.html')
flash('Incorrect data. Please try again.')
return render_template('login.html', username=username, password=password)
These last two lines of code will only execute if the entire file has been read, and no correct user matches were found. (If a match was found however, then the user will be logged in before the for block runs out of iterations, and have been already taken to your index page.)
You will also want to add strip() to this line of code:
login_info = line.split(',')
like so:
login_info = line.strip().split(',')
otherwise you will get a newline character (in your hashpass variable) and your verification check may fail.
I'm working on a web app right now and I don't know how to display an error message when the user types in an invalid log in name. How do I go about this?
this is my login.html
{% block body %}
<h1>Login</h1>
{% if error %}
<p>Invalid Username</p>
{% endif %}
<form method="POST" action="{{ url_for('login') }}">
<input type="text" name="username" placeholder="Your Username">
<input type="submit" value="Submit">
</form>
<a href='{{variable6}}'>Sign Up</a>
{% endblock %}
this is my app.py
#app.route("/login", methods=["GET", "POST"])
def login():
if flask.request.method == "GET":
return flask.render_template("login.html")
if flask.request.method == "POST":
username = flask.request.form["username"]
cursor.execute(
"SELECT user_name FROM public.users WHERE user_name = %s", [username]
)
results = cursor.fetchall()
if len(results) != 0: # if a user exists, "log" them in
return flask.redirect(flask.url_for("main"))
else:
return flask.render_template("login.html")
I believe that your problem is that you are not defining what the "error" variable is, you could fix this by when you are returning the render_template in the last line of app.py, adding error=True, leaving you with this as your last line for app.py.
return flask.render_template("login.html", error=True)
As otherwise Jinja (the templating language you used in login.html) would not know what error and would get the type None as the value of error in the {% if error %} statement in login.html and since None is not equal to true, it would skip over the code you want to run.
Hope this helps :)
I'm trying to build a web app using Python Flask that can perform CRUD operations for a database that already exists in PostgreSQL. Below I'm trying to perform the "Update Operation"
Here is my table for the database;
class Intern(db.Model):
intern_id = db.Column(db.Integer, primary_key=True)
intern_name = db.Column(db.String(150), nullable=True)
date_created = db.Column(db.DateTime, default=datetime.utcnow)
def __repr__(self):
return '<Name %r>' % self.intern_id
Following is my update function in "app.py";
#app.route('/update/<int:intern_id>', methods=['POST', 'GET'])
def update(intern_id):
intern_to_update = Intern.query.get_or_404(intern_id)
if request.method == "POST":
intern_to_update.intern_name = request.form['name']
try:
db.session.commit()
return redirect('/successful')
except:
return "There was a problem updating... Please try again!"
else:
return render_template('update.html', intern_to_update=intern_to_update)
Following is my successful function in "app.py". This function creates the intern.
#app.route('/successful', methods=['POST', 'GET'])
def successful():
if request.method == "POST":
intern_name = request.form["intern_name"]
new_intern = Intern(intern_name=intern_name)
if not intern_name:
show_error = "You need to fill out the forms required. Please try again."
return render_template("fail.html", show_error=show_error)
try:
db.session.add(new_intern)
db.session.commit()
return redirect('/successful')
except:
return "There was an error adding the new intern! Please try again"
else:
interns = Intern.query.order_by(Intern.date_created)
return render_template("successful.html", interns=interns)
Here is my "update.html" file;
{% extends 'base.html' %}
{% block title %}Update{% endblock %}
{% block content %}
<div class="container">
<h1>Update Operation</h1>
<br/><br/>
<form action="/update/{{intern_to_update.intern_id}}" method="POST">
<div class="mb-3">
<b><p> {% block info %} Please enter the credentials below {% endblock %} </p></b>
</div>
<div class="mb-3">
<input type="text" placeholder="Intern Name" name="name" value="{{intern_to_update.name}}">
</div>
<button type="submit" class="btn btn-primary" value="Update Name">Create</button>
</form>
<br/>
<div class="mb-3">
<b><p> Thank you, your operation is successfully completed! </p></b>
</div>
</div>
{% endblock %}
Lastly, below is where the update link is coming from in "base.html" file;
<li class="nav-item">
<a class="nav-link" href="{{url_for('update', intern_id = intern_to_update.intern_id)}}">Update</a>
</li>
There are no errors whatsoever with creating an intern. So my "successful" function is working without any mistakes. But I can't even see if my "update" function is working. Can someone please tell me why I'm getting this error I couldn't figure out? I checked other solutions for other users, which is usually adding "return render_template" for ELSE (GET) part for their code but I already did that.
Website Link: Click Me
The "Next" button isn't submitting. My HTML Code is:
{% extends "layout.html" %}
{% block main %}
<div style='float:left;width:70%;'>
<div style='margin-top:200px;'>
<form method='POST' action='/login1'>
<input type='hidden' value="{{path}}">
<input style='width:800px;height:60px;font-size: 2em;' type='email' placeholder='Type your email to continue...' name='email' value="{{name}}">
<style>
.sub:hover{
border-style:none;
}
.sub{
border-style:none;
}
</style>
<input class='sub' type='submit' value='Next' style='height:75px;'>
</form>
</div>
</div>
<div style='float:left;width:20%;'>
<!--<img height="100%" src='static/assets/AccountBanner.png'>!-->
</div>
{% endblock %}
My Python Flask code is:
#app.route('/login')
def login():
username = request.cookies.get('login')
psw = request.cookies.get('psw')
if 'login' in request.args.get('path'):
return redirect('/login?path=/')
if username == None:
return render_template('login/index.html',path = request.args['path'])
with open('static/json/members.json') as a:
a = json.load(a)
found = False
for i in a:
if i["email"] == username:
if str(i["password"]) != str(psw):
return redirect('/')
else:
found = True
if found == False:
return render_template('login/index.html',path=request.args['path'])
return redirect('/')
#app.route('/login1', methods=['POST'])
def main1():
return render_template('password.html',redirect1 = "/login1"+request.args['path'])
What I am trying to do is asking the user for his/her email and then render a page asking for a password. However, the submit button isn't working. I am using action and method=POST submit.
Ok, I know why it didn't work.
Everytime I make an error (syntax error) OR I POST to a 404 page, I have a 404 and 500 function where it makes you login before viewing the 404/500 page. That's why it kept on redirecting to the original login page. It works now.
I'm new to Flask, I'm using the apache-superset in version 0.38.0.
In it I'm using an LDAP authentication method, everything is functional.
However, I have another system in the company, which also uses LDAP to login, proprietary system. The idea is that when the user is logged in to our system and is going to enter the superset, he is already logged in, taking advantage of the credentials used in our system, since both are use LDAP.
What I've found so far: Apparently this is the class that authenticates LDAP credentials:
class AuthLDAPView(AuthView):
login_template = "appbuilder/general/security/login_ldap.html"
#expose("/login/", methods=["GET", "POST"])
def login(self):
if g.user is not None and g.user.is_authenticated:
return redirect(self.appbuilder.get_url_for_index)
form = LoginForm_db()
if form.validate_on_submit():
user = self.appbuilder.sm.auth_user_ldap(
form.username.data, form.password.data
)
if not user:
flash(as_unicode("Usuário não Encontrado ou Instabilidade no servidor LDAP"), "warning")
return redirect(self.appbuilder.get_url_for_login)
login_user(user, remember=False)
return redirect(self.appbuilder.get_url_for_index)
return self.render_template(
self.login_template, title=self.title, form=form, appbuilder=self.appbuilder
)
the credentials apparently received through LoginForm_db ():
class LoginForm_db(DynamicForm):
username = StringField(lazy_gettext("User Name"), validators=[DataRequired()])
password = PasswordField(lazy_gettext("Password"), validators=[DataRequired()])
which in turn receives the values from the login screen that is written in flask in the following:
<form class="form" action="" method="post" name="login">
{{form.hidden_tag()}}
<div class="help-block">{{_("Enter your login and password below")}}:</div>
<div class="control-group{% if form.errors.openid is defined %} error{% endif %}">
<label class="control-label" for="openid">{{_("Username")}}:</label>
<div class="controls">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-user"></i></span>
{{ form.username(size = 80, class = "form-control", autofocus = true) }}
</div>
{% for error in form.errors.get('openid', []) %}
<span class="help-inline">[{{error}}]</span><br>
{% endfor %}
<label class="control-label" for="openid">{{_("Password")}}:</label>
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-key"></i></span>
{{ form.password(size = 80, class = "form-control") }}
</div>
{% for error in form.errors.get('openid', []) %}
<span class="help-inline">[{{error}}]</span><br>
{% endfor %}
</div>
</div>
<div class="control-group">
<div class="controls">
<br>
<input class="btn btn-primary btn-block" type="submit" value="{{_('Logar')}}">
</div>
</div>
</form>
I was thinking of doing something that can send the credentials authenticated in our proprietary system (developed in java) through the url and receive them in this form of the superset and consequently log in.
I'm almost sure it shouldn't be the safest method, but I'm a beginner in programming and can't think of anything better. Maybe the Token but I don't even know where to start.
User logged into another system, (where I can redeem the user and password), when redirected to the superset, must be automatically logged in. How to do this ?
You can create a RESTful API to handle user authentication as below
from flask import request, make_response, jsonify, session
from flask_appbuilder.api import BaseApi, expose, rison, safe
from flask_appbuilder.security.decorators import protect
from . import appbuilder
from flask_login import current_user, login_user
from app import db
class LoginApi(BaseApi):
resource_name = "login"
#expose('/loginapi/', methods=['GET','POST'])
##has_access
def loginapi(self):
if request.method == 'POST':
username = request.json['username']
password = request.json['password']
user = self.appbuilder.sm.auth_user_db(username, password)
if str(user) != "None":
login_user(user, remember=False)
if current_user.is_active:
username = current_user.username
status = current_user.active
response = make_response(jsonify({'message': 'Login Success',
'severity': 'info','Username':
username,'Status':status}))
return response
For details on how to create a REST API refer to this this.
https://flask-appbuilder.readthedocs.io/en/latest/rest_api.html