Part 6 - Creating a web application with Flask - Sessions and restricting access
I've recently created my own web application using Flask and had some trouble with a few things, so once I figured them out, I thought I might as well make a tutorial series so others don't have to run into the same problems as myself! In this tutorial we will go through how to store information about a user, how to hide and show content depending on if a user is logged in or not, how to log a user out and how to restrict a user's access.
What will I learn
- How to store information about a user
- How to hide and show content
- How to log a user out
- How to restrict a user's access
Requirements
- Python2 or Python3.3+
Difficulty
- Intermediate
Tutorial
If you find it easier to follow along this way you can get the entire code for this tutorial from here, where I have split everything up into the relevant sections.
Logging in and sessions
In the next step we need to use session
which will allow us to store information specific to a user from one request to the next. To do this we can import session
from Flask (just like render_template
). Once we've done this we can use this to save information about the user once we have confirmed they are in the database and their password is correct. It's very important to know if a user is logged in for example, so we can just set the one of the session's keys to True and check this if we want to see if a user is logged in or not. After saving all the information we need we should redirect them to the homepage, and as you know we can use the redirect
function for this. Let's implement everything! Simply add this to our login()
function
if sha512_crypt.verify(password, fetched_password):
# So we know if a user is logged in or not
session["logged_in"] = True
# Save their name so we can display it when they are logged in
session["name"] = name
# Redirect the user
return redirect(url_for("feed"))
Let's also make sure the buttons in navbar.html
are actually working and take us to register.html
and login.html
by changing their href
attributes to equal {{ url_for('register') }}
and {{ url_for('login') }}
respectively. It would also be nice if clicking "steemit" would take us to index.html
, so add that as well by wrapping it in <a href="{{ url_for('index') }}">steemit</a>
.
Hiding and showing content
When a user is logged in we don't want to show them the "Login" and "Sign up" buttons, as that doesn't make any sense. We also don't want to show a user someone's feed when they aren't actually logged in either. Since we have now created a session, we can check the "logged_in" key and either show or hide content based on its value! Let's start with hiding the buttons in the navbar if a user is logged in or not, and instead show their username. To do this we can simply add an if else statement to our navbar.html
, as shown below
{% if session.logged_in %}
{{ session.name }}
{% else %}
<a class="btn btn-outline-primary mr-md-3" href="{{ url_for('register') }}">Sign up</a>
<a class="btn btn-outline-primary" href="{{ url_for('login') }}">Login</a>
{% endif %}
which results in the following navbar
Logging out
Before we continue we should also add the ability for a user to log out. If a user logs out, all we have to do is clear their session and then either redirect them to index.html
or login.html
(whichever you prefer). To do this we can add the following code to app.py
@app.route("/logout")
def logout():
# Clear the user's session, it's that easy
session.clear()
# Redirect the user
return redirect(url_for("index"))
Let's also add a button to navbar.html
that allows the user to log out by clicking it, instead of having to manually navigate to /logout
.
{% if session.logged_in %}
{{ session.name }}
<a class="btn btn-outline-primary ml-md-3" href="{{ url_for('logout') }}">Logout</a>
{% else %}
Since it returns the URL for the logout
function it also calls that function, which clears the user's session, causing them to log out!
Restricting access
For some pages we would want the user to be logged in, so we need to restrict access if a user isn't logged in. To do this we can use view decorators
, which is explained thoroughly here. Let's import everything they import and take their login_required()
function and adapt it to suit our needs! So instead of the example they give
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if g.user is None:
return redirect(url_for('login', next=request.url))
return f(*args, **kwargs)
return decorated_function
we should have the following code. Here we check if a user is logged in, and if they are, we allow them to see the page they are trying to access. If that's not the case, we redirect them to the login page, since they need to do that before they can see what they want to see
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
# If user is logged in, then allow them to see content
if "logged_in" in session:
return f(*args, **kwargs)
# Otherwise redirect them to the login page!
return redirect(url_for("login"))
return decorated_function
To use this function to restrict access to a certain page we can simply add the decorator @login_required
in between the route and the function that returns the template, like so
@app.route("/feed")
@login_required
def feed():
return render_template("feed.html", posts=posts)
Now if we try to access /feed
without loggin in we will be redirected to the login page!
Congratulations, you've now learned how to store information about a user, how to hide and show content depending on if a user is logged in or not, how to log a user out and how to restrict a user's access.
Curriculum
- Part 1 - Creating a web application with Flask - Initial setup and routes
- Part 2 - Creating a web application with Flask - Including and extending templates
- Part 3 - Creating a web application with Flask - For loops, creating a database and forms
- Part 4 - Creating a web application with Flask - Handling form data
- Part 5 - Creating a web application with Flask - Redirecting and logging in
The code for this tutorial can be found on GitHub!
In the next tutorial we will find out how to add dynamic variables to routes, retrieve a user from your database, display their information and use Font Awesome's icons.
Posted on Utopian.io - Rewarding Open Source Contributors
Thank you for the contribution. It has been approved.
You can contact us on Discord.
[utopian-moderator]
Thanks!
@amosbastian, I always try to support who contribute to open source project, upvote you.
Hey @amosbastian I am @utopian-io. I have just upvoted you!
Achievements
Suggestions
Get Noticed!
Community-Driven Witness!
I am the first and only Steem Community-Driven Witness. Participate on Discord. Lets GROW TOGETHER!
Up-vote this comment to grow my power and help Open Source contributions like this one. Want to chat? Join me on Discord https://discord.gg/Pc8HG9x