I have a Python code with using framework Flask, that check if admin logged (logged = True) to render admin page, if admin is not logged (logged = False), redirecting to login page.
#app.route('/admin_login', methods=['POST', 'GET'])
def admin_login():
if request.method == 'POST':
login = request.form['login']
passsword = request.form['password']
if (login == 'admin') and (passsword == 'admin_pass'):
logged = True
return redirect('/admin_page'), logged
else:
return "Wrond login and passsword!"
else:
return render_template('admin_login.html')
#app.route('/admin_page')
def admin_page():
if logged == True:
return render_template('admin_page.html')
else:
return redirect('/admin_login')
But I get an error in if logged == True: - NameError: name 'logged' is not defined. I tried to make logged global but it didn't helped. So how can I make logged defined and use it in function admin_page?
You should avoid having a global logged_in variable on the server. Then anybody will be allowed to use your website after a successful login! You should use a session variable instead.
Session data is stored on top of cookies and encrypted. For this encryption, a Flask application needs a defined SECRET_KEY. A Session object is also a dictionary object containing key-value pairs.
Add this near the top of your main script if you haven't already got it:
from flask import Flask, session, redirect, url_for, escape, request, flash
app = Flask(__name__)
app.secret_key = 'any random string’
Then change your function admin_login() to set the session variable:
#app.route('/admin_login', methods=['POST', 'GET'])
def admin_login():
if request.method == 'POST':
login = request.form['login']
passsword = request.form['password']
if not 'logged_in' in session:
if (login == 'admin') and (passsword == 'admin_pass'):
session['logged_in'] = True
return redirect(url_for("admin_page"))
else:
flash("Wrong login and passsword!")
return render_template('admin_login.html')
else:
return redirect(url_for("admin_page"))
else:
if "logged_in" in session:
return redirect(url_for("admin_page"))
return render_template("admin_login.html")
Then change your admin_page() function to check this session variable:
#app.route('/admin_page')
def admin_page():
if 'logged_in' in session:
return render_template('admin_page.html')
else:
return redirect(url_for('admin_login'))
You would also need a logout end point to pop out the session variable:
#app.route('/logout')
def logout():
session.pop('logged_in', None)
return redirect(url_for('index'))
Related
I've made a successfull login to a html page (lets call it page1). Now I need to allow access to a second page (page2) only if the user has previously done the login. I think I need an IF to specify to which page the user is attempting to go: page1 or page2.
This is what I got:
#app.route('/user')
def user():
if "user" in session:
user = session["user"]
return render_template("page1.html")
else:
return redirect(url_for("login"))
This following is wrong, I need that IF:
def user():
if "user" in session:
user = session["user"]
if ... : # user attempting to go to page 1
return render_template("page1.html")
else:
return render_template("page2.html")
else:
return redirect(url_for("login"))
Thanks to all
Edited, to share the login method:
#app.route('/login', methods = ["GET","POST"])
def login():
error = None;
if request.method == "POST":
user = request.form["email"]
with open("users.txt", "r") as file:
file_reader = csv.reader(file)
for row in file_reader:
if row[0] == request.form['email']:
user_found = [row[0],row[1]]
if user_found[1] != request.form['pass']:
error = "wrong pass"
break
else:
flash("logged in")
session["user"]= user
return redirect(url_for('user'))
else:
error = "user not found"
else:
if "user" in session:
return redirect(url_for("user"))
return render_template('login.html',error=error)
a better way to do this is to use flask-login. Views that require your users to be logged in can be decorated with the login_required decorator:
after installing flask-login, put the following in your main file or init.py
...
app = Flask(__name__) # constructs the Flask app
app.config.from_object('app.config.Config') # injects the configuration
db = SQLAlchemy (app) # flask-sqlalchemy # connects to SQLite DB
lm = LoginManager( ) # flask-loginmanager
lm.init_app(app) # init the login manager
then create your user model and inherit from user_mixin that provides default implementations for the methods that Flask-Login expects
class User(db.model, user_mixin):
then define the user loader
#login_manager.user_loader
def load_user(user_id):
return User.get(user_id)
in your login route, after checking the username and password (enc) add the following to login the user:
login_user(user)
now you can decorate your protected views with login_required
#app.route("/page2")
#login_required
def page2():
return render_template("page2.html")
#app.route("/page3")
#login_required
def page3():
return render_template("page3.html")
You can implement a wrapper function to check if a user is logged in. In that function utilize the global g variable.
from flask import g
from functools import wraps
def login_required(f):
#wraps(f)
def decorated_function(*args, **kwargs):
if not "user" in session:
return redirect(url_for('login'))
g.user = session["user"]
return f(**args, **kwargs)
return login_required
#app.route('/user')
#login_required
def user():
return render_template("page1.html")
For a full example take a look at the View Decorators portion of the Flask documentation
I am creating a basic application to demonstrate the register and login activities in Flask using sessions. For the below code, each user available in the dictionary should be able to login. However, the application only accepts the login for the first user named 'Mary'. I don't understand where did it went wrong.
from flask import Flask, app, session, render_template, request,redirect, url_for, jsonify
app = Flask(__name__)
app.config['SECRET_KEY'] = "Zd9TUg1aE03bHc28"
#app.route('/')
def load():
return render_template("authusers.html")
class Mydatabase:
appdb=[{'username':'Mary','password':'Password#123'},
{'username':'John','password':'Password#456'},
{'username':'Tara','password':'Password#789'}]
mydbusers=Mydatabase()
#app.route('/login',methods = ['GET','POST'])
def success():
if request.method == "POST":
username_val = request.form['user_id']
userpassword_val = request.form['user_password']
for authuser in Mydatabase.appdb:
for authpassword in authuser.values():
if authuser['username'] == username_val and authpassword['password'] == userpassword_val:
session['reg_user'] = username_val
return f'{session.get("reg_user")} have successfully logged into the application';
else:
return redirect(url_for('register'))
#app.route('/logout', methods=['GET','POST'])
def logout():
if 'reg_user' in session:
session.pop('reg_user',None)
return render_template("authusers.html")
#app.route('/register', methods=['GET','POST'])
def register():
return render_template('register.html')
#app.route('/reg_success',methods=['GET','POST'])
def reg_success():
newusercred={'username':request.form['user_id'], 'password':request.form['user_password']}
mydbusers.appdb.append(newusercred)
# return jsonify(Mydatabase.appdb)
return render_template("authusers.html")
if __name__=="__main__":
app.run(debug=True)
I see some logical issue in your code
Try like this ->
class Mydatabase:
appdb=[{'username':'Mary','password':'Password#123'},
{'username':'John','password':'Password#456'},
{'username':'Tara','password':'Password#789'}]
username_val = 'Tara'
userpassword_val = 'Password#789'
d = [a for a in Mydatabase.appdb if a["username"] == username_val and a["password"]==userpassword_val]
if d:
print(f'have successfully logged into the application')
else:
print(f'Wrong credentials')
There are some unwanted loops in your code, and you do return even in the else of part.
When I login I can store on session but it seems after that session will be empty because I can't go to profile? I also tried from flask_session import Session , app.config.from_object(name) but it still have same issue? Also I send request from react.
from flask import Flask, request, jsonify, session
app.secret_key = "tutorialtutorial"
#app.route('/login',methods=['GET','POST'])
def login():
data = request.get_json()
user = User.query.filter_by(email=data.get("email")).one()
print(user)
if not user:
return "no user"
else:
if bcrypt.check_password_hash(user.password,data.get("password")):
# create sesion
session['user'] = user.firstname
print(session)
return "Authorized"
else:
return "UnAthorized"
# if user is not null
return "Hello login!"
#app.route('/profile',methods=['POST'])
def profile():
print(session)
print(len(session))
if "user" in session:
return "Hello Here is your profile"
else:
return "You are not defined" ```
app = Flask(__name__)
firebase = pyrebase.initialize_app(config)
auth = firebase.auth()
db = firebase.database()
#app.route('/login', methods=["POST", "GET"])
def login():
message = ""
if request.method == "POST":
email = request.form["login_email"]
password = request.form["login_password"]
try:
user = auth.sign_in_with_email_and_password(email, password)
user = auth.refresh(user['refreshToken'])
user_id = user['idToken']
return redirect(url_for('admin'))
except:
message = "Incorrect Password!"
return render_template("login.html", message=message)
#app.route('/admin')
def admin():
return render_template("admin.html")
if __name__ == '__main__':
app.run()
How can I only load /admin page when the user is logged in? I know it has something to do with the user token, but I'm still not sure about how I could use the token to identify whether the user is logged in or not. Also, the user and user_id are not defined in admin()and only in login() since they're in a function.
So what do I need to change in my code in order to only load the /admin page when the user is logged in?
use flask session to store your key,if key exist then user is logged,
also you can access all session variables globally for individual session
from flask import Flask, session, request
import requests
import os
app = Flask(__name__)
app.secret_key = os.urandom(24)
firebase = pyrebase.initialize_app(config)
auth = firebase.auth()
db = firebase.database()
#app.route('/login', methods=["POST", "GET"])
def login():
message = ""
try:
print(session['usr'])
return redirect(url_for('admin'))
except KeyError:
if request.method == "POST":
email = request.form["login_email"]
password = request.form["login_password"]
try:
user = auth.sign_in_with_email_and_password(email, password)
user = auth.refresh(user['refreshToken'])
user_id = user['idToken']
session['usr'] = user_id
return redirect(url_for('admin'))
except:
message = "Incorrect Password!"
return render_template("login.html", message=message)
#app.route('/admin')
def admin():
try:
print(session['usr'])
return render_template("admin.html")
except KeyError:
return redirect(url_for('login'))
if __name__ == '__main__':
app.run()
if session['usr'] is not assigned then it will give key error which means that usr in not logged in. but note that in the process of logout you need to delete the session for that usr.
I have built a website using flask (www.csppdb.com). Sometimes when I log in as one user, log out, then login as another user I still see pages from the first user I logged in as. This problem is immediately fixed when the page is refreshed. I think this is called "caching" if I am not mistaken. Is there any way I could disable this on a site wide level so that every page that is visited needs a new refresh?
It would be like sharing your computer with a friend. He logs into Facebook, then logs out. Now you log in on his computer and you see his profile... (awkward). After you refresh the page the problem is fixed.
Here is some of my code. I was using flask-login but I then tried to "roll my own"
from flask.ext.mysql import MySQL
import os
from flask import Flask, request, jsonify, session, url_for, redirect, \
render_template, g, flash
from data import *
from werkzeug import check_password_hash, generate_password_hash
import config
app = Flask(__name__)
mysql = MySQL()
app.config['MYSQL_DATABASE_HOST'] = os.environ['MYSQL_DATABASE_HOST'] if 'MYSQL_DATABASE_HOST' in os.environ else config.MYSQL_DATABASE_HOST
app.config['MYSQL_DATABASE_PORT'] = os.environ['MYSQL_DATABASE_PORT'] if 'MYSQL_DATABASE_PORT' in os.environ else config.MYSQL_DATABASE_PORT
app.config['MYSQL_DATABASE_USER'] = os.environ['MYSQL_DATABASE_USER'] if 'MYSQL_DATABASE_USER' in os.environ else config.MYSQL_DATABASE_USER
app.config['MYSQL_DATABASE_PASSWORD'] = os.environ['MYSQL_DATABASE_PASSWORD'] if 'MYSQL_DATABASE_PASSWORD' in os.environ else config.MYSQL_DATABASE_PASSWORD
app.config['MYSQL_DATABASE_DB'] = os.environ['MYSQL_DATABASE_DB'] if 'MYSQL_DATABASE_DB' in os.environ else config.MYSQL_DATABASE_DB
mysql.init_app(app)
if 'SECRET_KEY' in os.environ: app.config['SECRET_KEY'] = os.environ['SECRET_KEY']
else: app.config['SECRET_KEY'] = os.urandom(24)
def connect_db(): return mysql.connect()
def check_auth():
g.user = None
if 'username' in session:
g.user = get_user(session['username'])
return
return redirect(url_for('login'))
#app.route('/')
def home():
if 'username' in session: return redirect(url_for('main'))
return render_template('home.html')
def connect_db(): return mysql.connect()
#app.teardown_request
def teardown_request(exception):
if exception: print exception
g.db.close()
#app.before_request
def before_request():
print session.keys(), session.values()
print("before request")
print ('username' in session, "in session?")
g.db = connect_db()
g.user = None
if "username" in session:
g.user = get_user(session['username'])
#app.route('/login/', methods=['GET', 'POST'])
def login():
"""Logs the user in."""
if 'username' in session:
return redirect(url_for('main'))
error = None
if request.method == 'POST':
print("login hit")
user = get_user(request.form['username'])
if user is None:
error = 'Invalid username'
print error
elif not check_password_hash(user.password, request.form['password']):
error = 'Invalid password'
print error
else:
flash('You were logged in')
print "logged in"
session['username'] = request.form['username']
g.user = request.form['username']
print error, "error"
return redirect(url_for('main'))
return render_template('login.html', error=error)
Setting the cache to be max-age=0 fixed it.
#app.after_request
def add_header(response):
"""
Add headers to both force latest IE rendering engine or Chrome Frame,
and also to cache the rendered page for 10 minutes.
"""
response.headers['X-UA-Compatible'] = 'IE=Edge,chrome=1'
response.headers['Cache-Control'] = 'public, max-age=0'
return response
To stop browser caching on these sort of pages you need to set some HTTP response headers.
Cache-Control: no-cache, no-store
Pragma: no-cache
Once you do this then the browser wont cache those pages. I dont know how to do this with "flask" so I will leave that as an exercise for you :)
This question shows how to add a response header Flask/Werkzeug how to attach HTTP content-length header to file download