CREATE TABLE users ( username VARCHAR(20) NOT NULL, password VARCHAR(64) NOT NULL, PRIMARY KEY (username) );
Before being stored in the database, passwords will be encrypted using a non-reversible, one-way encryption algorithm (SHA256)
index.html
index.html
is just a welcome page
register.py
(for new users) and login.py
(for existing users)
<a href="login.py">Login</a> <a href="register.py">Register new user</a>
register.py
: pseudocodeA (partly) sticky, self-processing page
result = '' if the user is sending us data: if username blank or passwords blank or passwords not equal: result = error message else: if username already in database: result = error message else: encrypt password insert new user details in database create a cookie containing a session id store data about this user in session store result = the 'protected' content output the cookie output Web page containing form and 'result'
register.py
: the Python#!/usr/local/bin/python3 from cgitb import enable enable() from cgi import FieldStorage from html import escape from hashlib import sha256 from time import time from shelve import open from http.cookies import SimpleCookie import pymysql as db form_data = FieldStorage() username = '' result = '' if len(form_data) != 0: username = escape(form_data.getfirst('username', '').strip()) password1 = escape(form_data.getfirst('password1', '').strip()) password2 = escape(form_data.getfirst('password2', '').strip()) if not username or not password1 or not password2: result = '<p>Error: user name and passwords are required</p>' elif password1 != password2: result = '<p>Error: passwords must be equal</p>' else: try: connection = db.connect('localhost', 'userid', 'password', 'database_name') cursor = connection.cursor(db.cursors.DictCursor) cursor.execute("""SELECT * FROM users WHERE username = %s""", (username)) if cursor.rowcount > 0: result = '<p>Error: user name already taken</p>' else: sha256_password = sha256(password1.encode()).hexdigest() cursor.execute("""INSERT INTO users (username, password) VALUES (%s, %s)""", (username, sha256_password)) connection.commit() cursor.close() connection.close() cookie = SimpleCookie() sid = sha256(repr(time()).encode()).hexdigest() cookie['sid'] = sid session_store = open('sess_' + sid, writeback=True) session_store['authenticated'] = True session_store['username'] = username session_store.close() result = """ <p>Succesfully inserted!</p> <p>Thanks for joining Web Dev 2.</p> <ul> <li><a href="protected_page_A.py">Web Dev 2 - Members Only A</a></li> <li><a href="protected_page_B.py">Web Dev 2 - Members Only B</a></li> <li><a href="logout.py">Logout</a></li> </ul>""" print(cookie) except (db.Error, IOError): result = '<p>Sorry! We are experiencing problems at the moment. Please call back later.</p>' print('Content-Type: text/html') print() print(""" <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Web Dev 2</title> </head> <body> <form action="register.py" method="post"> <label for="username">User name: </label> <input type="text" name="username" id="username" value="%s" /> <label for="password1">Password: </label> <input type="password" name="password1" id="password1" /> <label for="passwords2">Re-enter password: </label> <input type="password" name="password2" id="password2" /> <input type="submit" value="Register" /> </form> %s </body> </html>""" % (username, result))
login.py
: pseudocode
Also a (partly) sticky, self-processing page, and
very similar to register.py
result = '' if the user is sending us data: if username blank or password blank: resut = error message else: encrypt password search for username and encrypted password in database if they aren't there: result = error message else: create a cookie containing a session id store data about this user in session store result = the 'protected' content output the cookie output Web page containing form and 'result'
login.py
: the Python#!/usr/local/bin/python3 from cgitb import enable enable() from cgi import FieldStorage from html import escape from hashlib import sha256 from time import time from shelve import open from http.cookies import SimpleCookie import pymysql as db form_data = FieldStorage() username = '' result = '' if len(form_data) != 0: username = escape(form_data.getfirst('username', '').strip()) password = escape(form_data.getfirst('password', '').strip()) if not username or not password: result = '<p>Error: user name and password are required</p>' else: sha256_password = sha256(password.encode()).hexdigest() try: connection = db.connect('localhost', 'userid', 'password', 'database_name') cursor = connection.cursor(db.cursors.DictCursor) cursor.execute("""SELECT * FROM users WHERE username = %s AND password = %s""", (username, sha256_password)) if cursor.rowcount == 0: result = '<p>Error: incorrect user name or password</p>' else: cookie = SimpleCookie() sid = sha256(repr(time()).encode()).hexdigest() cookie['sid'] = sid session_store = open('sess_' + sid, writeback=True) session_store['authenticated'] = True session_store['username'] = username session_store.close() result = """ <p>Succesfully logged in!</p> <p>Welcome back to Web Dev 2.</p> <ul> <li><a href="protected_page_A.py">Web Dev 2 - Members Only A</a></li> <li><a href="protected_page_B.py">Web Dev 2 - Members Only B</a></li> <li><a href="logout.py">Logout</a></li> </ul>""" print(cookie) cursor.close() connection.close() except (db.Error, IOError): result = '<p>Sorry! We are experiencing problems at the moment. Please call back later.</p>' print('Content-Type: text/html') print() print(""" <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Web Dev 2</title> </head> <body> <form action="login.py" method="post"> <label for="username">User name: </label> <input type="text" name="username" id="username" value="%s" /> <label for="password">Password: </label> <input type="password" name="password" id="password" /> <input type="submit" value="Login" /> </form> %s </body> </html>""" % (username, result))
protected_page_A.py
/protected_page_B
:
the 'protected' content
logout.py
protected_page_A.py
:
the 'protected' content
#!/usr/local/bin/python3 from cgitb import enable enable() from os import environ from shelve import open from http.cookies import SimpleCookie print('Content-Type: text/html') print() result = """ <p>You do not have permission to access this page.</p> <ul> <li><a href="register.py">Register</a></li> <li><a href="login.py">Login</a></li> </ul>""" try: cookie = SimpleCookie() http_cookie_header = environ.get('HTTP_COOKIE') if http_cookie_header: cookie.load(http_cookie_header) if 'sid' in cookie: sid = cookie['sid'].value session_store = open('sess_' + sid, writeback=False) if session_store.get('authenticated'): result = """ <p> Hey, %s. We hope you enjoy this photo! </p> <img src="photo1.jpg"> <ul> <li><a href="protected_page_A.py">Web Dev 2 - Members Only A</a></li> <li><a href="logout.py">Logout</a></li> </ul>""" % session_store.get('username') session_store.close() except IOError: result = '<p>Sorry! We are experiencing problems at the moment. Please call back later.</p>' print(""" <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Web Dev 2</title> </head> <body> %s </body> </html>""" % (result))
logout.py
#!/usr/local/bin/python3 from cgitb import enable enable() from os import environ from shelve import open from http.cookies import SimpleCookie print('Content-Type: text/html') print() result = '<p>You are already logged out</p>' try: cookie = SimpleCookie() http_cookie_header = environ.get('HTTP_COOKIE') if http_cookie_header: cookie.load(http_cookie_header) if 'sid' in cookie: sid = cookie['sid'].value session_store = open('sess_' + sid, writeback=True) session_store['authenticated'] = False session_store.close() result = """ <p>You are now logged out. Thanks for using Web Dev 2</p> <p><a href="login.py">Login again</a></p>""" except IOError: result = '<p>Sorry! We are experiencing problems at the moment. Please call back later.</p>' print(""" <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Web Dev 2</title> </head> <body> %s </body> </html>""" % (result))