1. Project 2 – Secure Web Forum
In this project, you will be building a secure web forum. In this forum, users can create their own accounts
in order to post contents into the forum. These posted contents should be checked against SQL injection
as well as against XSS. Moreover, users’ passwords are only stored in hashed format using a salt.
General Instructions
In this forum, as it I the case for most forums, everyone can see the posts from other users. However, a
user needs to sign in in order to post. All posts show the title and author at the top, and the contents just
below (see Figure 1).
Every time a new post is added, it should appear below the last post. This way, newer posts always appear
at the bottom.
In case the user has logged in, the forum should greet him/her and provide him/her with a form to enter
a new post (see Figure 1 again). In case the user has not logged in, the forum should provide him/her
with a form to login (see Figure 2), as well as a hyperlink that, once clicked, takes the user to a page in
which he/she can create a new account (see Figure 3). Once an account has been successfully created,
the user should be redirected back to the main forum page.
Figure 1: Forum web page (user logged in)
2. Specific Instructions
For this project, you will create a web forum where users can view posts from other users, sign in, login,
and create posts. To achieve this, you will have to create Python scripts to perform the actions described
below.
As opposed to the previous project, where students were asked to create a specific set of functions, you
will have complete control about how to set up your system this time. Therefore, different students might
have different sets of scripts and/or functions. Be creative! The only constraint is that your system must
have a main page called forum.py. Hint: To help you with writing the dynamically generated HTML
code, the output of calling forum.py while being signed in and while not being signed in is provided as
static html pages. I am also providing an HTML implementation of the sign in form. Feel free to use or
not these provided pages.
Note that you will have to create a database with two tables: users (containing information about all user
accounts) and posts (containing information about all posts). These tables should be created in MySQL
in such a way that they meet all requirements imposed by the actions your system need to perform
(described below). This database must be exported and submitted together with all Python scripts. I
strongly advise students to put this exported database in a folder, together with all scripts, zip the entire
folder, and submit this zipped folder. To export a MySQL database, you should perform the following
command in your terminal:
mysqldump -p -u USERNAME DATANASE_NAME > FILENAME.sql
Figure 2: Forum web page (user not logged in)
Figure 3: Sign in page
3. a) create a new account: Each account should take only two fields: a username and a password.
Passwords should be stored in a hashed format, using a SHA512 hash (including a salt).
Passwords must abide to the following rules: at least one uppercase character, at least one
lowercase character, and at least one number. Note that the system should prevent a new user to
be added in case the username matches a username that already exists in the database. Once a
new account has been successfully created, your system should load the main forum page. Your
system should present meaningful error messages, whenever something does not work as
planned. For example, it should let the user know that there is already a user with that username,
or if the user’s password does not match the required criteria. (3.0 marks)
b) login: In order to login, the user must enter his/her username and password in a form (see Figure
2). The system must check the username and password against the rows in your users table in the
database. Note that passwords are stored in hashed format (using a SHA512 hash). After
successfully verifying that the user has entered the proper credentials, your script should save the
username and password in a cookie. Then it should load the forum page, showing again all posts,
but with one major change: the user can now enter new posts (see Figure 1). Your system should
present meaningful error messages whenever something does not work as planned. (3.0 marks)
c) create a new post: Each post has three fields: title, contents, and author. Note that the title and
contents must be provided via a form (see Figure 1), whereas the author information should be
obtained by reading the username information present in the cookie that was created as the user
signed in. Once a new post is created, the main forum page should be reloaded, showing this post.
(3.0 marks)
d) SQL injection and XSS: Your system should be secured against SQL injection and XSS. (3.0
marks)
e) Code quality: 3.0 marks for this project will be assigned based on the quality of your code, based
on the guidelines provided at the end of this document. (3.0 marks)
4. Guidelines
• Make sure to include a comment at the start of your program identifying yourself, the course, the
assignment, etc.
• Put a docstring inside each function and/or script to identify what the parameters represent, what
the return value (if any) represents, and a one line statement of what the function does. To see
what docstrings are, refer to: https://www.python.org/dev/peps/pep-0257/
• Put comments within functions, whenever you are doing something that would not be self-evident
to someone reading your program. Don't put a comment on every line - too many are as bad as
not enough.
• Put blank lines above and below functions to separate them from each other.
• Don't put in extra blank lines. (Some people put a blank lines between every line of code!)
• Read and understand the specifications. If you do not understand the specifications, ask me for
clarification. If you do not implement something required, you will lose marks, even if you didn't
understand the requirement - i.e. it is your job to seek clarification.
• Do not change the specifications. If you print something out and the assignment does not tell you
to print it out, you are changing the specification and will lose marks.
• Format your output to look, as much as possible, like the sample shown in the specification. The
closer it looks, the better your mark will be.
• Get rid of unnecessary (and confusing) duplication. For code, you can do this by factoring out
common code and putting it into a function. In a regex, you can always delete {1} because it
simply means the character in front of it repeats exactly once, but they always do by default! I
also noticed several people were including parentheses in regexes, but they served no purpose.
For example, '([0-9]{1})' is the same as '[0-9]'. Why make it look more complicated than need
be?
• Indent the same number of spaces. Always.
• Use four spaces for each indentation group.
• Develop your code anywhere you like, but make sure your code runs under Ubuntu and looks
nice in Visual Studio Code or Gedit. The former is what I use to check it.
• If you develop your code in Windows, don't submit it without testing it on Ubuntu. Transferring
source files from Windows to Linux requires transferring them in ASCII mode - and dragging
and dropping often transfers files in binary mode. If transferred in binary mode, you will get extra
characters in your file and the Python interpreter won't understand, and your program will crash.
5. • Do not leave external resources "open" when your program terminates (i.e. close all file
objects).
• Do not open and close a resource every time you want to write something to it if you are doing
so in a tight loop. Open it before the loop, and close it after the loop.
• Make sure your code is efficient. There are multiple ways to accomplish the same result.
However, some ways are clearly inefficient. For example, iterating over a list twice or three times,
when the task could have been done iterating over it only once is clearly an example of
inefficiency.
• Use meaningful names for your variables. For example if you have a variable that stores a set of
users, it is better to name it user_set instead of var37.
• Do not create variables to hold values from the outputs of functions if these values are only used
once. For example, given that the output of a function called func1 needs to be used as an input
argument to a function called func2, you shoud write your code as:
func2(func1())
instead of
unnecessary_var = func1()
func2(unnecessary_var)