1
0
mirror of https://github.com/avatao-content/test-tutorial-framework synced 2025-06-29 11:55:12 +00:00

Strip old sqli example app and replace it with a simple login service

This commit is contained in:
Kristóf Tóth
2018-04-25 11:52:42 +02:00
parent 54b299e7ef
commit 1a295d5fd6
15 changed files with 250 additions and 70 deletions

Binary file not shown.

View File

@ -0,0 +1,120 @@
from os import urandom, getenv
from os.path import exists, join, dirname, realpath
from hashlib import sha512
import sqlite3
from flask import Flask, render_template, request, g, session, url_for
def setup_db(filename):
connection = sqlite3.connect(filename)
cur = connection.cursor()
cur.execute('''CREATE TABLE users
(
id INTEGER PRIMARY KEY,
username TEXT NOT NULL,
pwhash TEXT NOT NULL
)
''')
connection.commit()
connection.close()
BASEURL = getenv('BASEURL', '')
DBFILE = join(dirname(realpath(__file__)), '.db.db')
SALT = 'justsomerandombytes'.encode()
if not exists(DBFILE):
setup_db(DBFILE)
app = Flask(__name__)
app.secret_key = urandom(32)
def get_url(endpoint):
return f'{BASEURL}{url_for(endpoint)}'
app.jinja_env.globals.update(get_url=get_url)
@app.before_request
def init_database():
g.db = sqlite3.connect(DBFILE)
g.db.row_factory = sqlite3.Row
@app.teardown_request
def close_database(exception):
db = getattr(g, 'db', None)
if db is not None:
db.close()
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
cur = g.db.cursor()
cur.execute('SELECT * FROM users WHERE username=? AND pwhash=?',
[request.form['username'], sha512(request.form['password'].encode()+SALT).hexdigest()])
query = cur.fetchone()
if not query:
return render_template('login.html', alert='Invalid credentials!')
else:
session['logged_in'] = True
session['username'] = request.form['username']
return render_template('internal.html')
if session.get('logged_in'):
return render_template('internal.html')
return render_template('login.html')
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
cur = g.db.cursor()
if not request.form['username'] or not request.form['password'] or not request.form['passwordconfirm']:
return render_template('register.html', alert='You need to fill everything.')
if request.form['password'] != request.form['passwordconfirm']:
return render_template('register.html', alert='Passwords do not match! Please try again.')
cur.execute('SELECT * FROM users WHERE username=?', [request.form['username']])
if cur.fetchone() is not None:
return render_template('register.html', alert='Username already in use.')
cur.execute('INSERT INTO users(username, pwhash) VALUES(?,?)',
[request.form['username'],
sha512(request.form['password'].encode()+SALT).hexdigest()])
g.db.commit()
return render_template('login.html', success='Account "{}" successfully registered. You can log in now!'.format(request.form['username']))
return render_template('register.html')
@app.route('/logout')
def logout():
try:
session.pop('logged_in')
session.pop('username')
except KeyError:
pass
return render_template('login.html')
@app.errorhandler(401)
@app.errorhandler(404)
@app.route('/error')
def error(error):
return render_template('error.html', error=error), error.code
# 500 needs a separate handler, as Flask would print
# the actual piece of code that caused the exception
# for some bizarre reason
@app.errorhandler(500)
@app.route('/error')
def servererror(error):
return render_template('error.html', error='500: Internal server error'), 500
if __name__ == '__main__':
app.run(host='127.0.0.1', debug=False, port=6666)

View File

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="static/bootstrap-3.3.7/css/bootstrap.min.css">
<script src="static/jquery-3.2.1.min.js"></script>
<script src="static/bootstrap-3.3.7/js/bootstrap.min.js"></script>
<script>
{% block script %}
{% endblock %}
</script>
<style>
.jumbotron h1 a
{
color: inherit;
text-decoration: none;
}
{% block style %}
{% endblock %}
</style>
</head>
<body>
<div class="jumbotron text-center">
<h1><a href="{{get_url('index')}}">SomeSite</a></h1>
<p>We provide stuff!</p>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3 col-sm-12">
{% if alert or success %}
<div class="alert alert-{{'success' if success else 'danger'}} alert-dismissable fade in center-block">
<a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
<div class="message">{{alert}}{{success}}</div>
</div>
{% endif %}
{% block content %}
{% endblock %}
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,6 @@
{% extends "base.html" %}
{% block content %}
<h3>Oops, something went wrong! :(</h3>
<h2>{{error}}</h2>
{% endblock %}

View File

@ -0,0 +1,9 @@
{% extends "base.html" %}
{% block content %}
<h2>Welcome, {{session.username}}</h2>
<p>You have successfully logged in</p>
<a href="{{get_url('logout')}}" class="btn btn-default" >
<span class="glyphicon glyphicon-log-out"></span> Logout
</a>
{% endblock %}

View File

@ -0,0 +1,27 @@
{% extends "base.html" %}
<style>
{% block style %}
{% endblock %}
</style>
<script>
{% block script %}
{% endblock %}
</script>
{% block content %}
<h2>Login</h2>
<form method="post" action="{{get_url('index')}}">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<input type="text" name="username" class="form-control" placeholder="Username" autofocus required />
</div>
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
<input type="password" name="password" class="form-control" placeholder="Password" required />
</div>
<div class="well">Not a member yet? <a href="{{get_url('register')}}">Register here</a>.</div>
<input type="submit" class="btn btn-success" value="Login!" />
</form>
{% endblock %}

View File

@ -0,0 +1,20 @@
{% extends "base.html" %}
{% block content %}
<h2>You can register using this form.</h2>
<form method="post" action="{{get_url('register')}}">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
<input type="text" name="username" class="form-control" placeholder="Username" autofocus required />
</div>
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
<input type="password" name="password" class="form-control" placeholder="Password" required />
</div>
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
<input type="password" name="passwordconfirm" class="form-control" placeholder="Confirm password" required />
</div>
<input type="submit" class="btn btn-success" value="Register!" />
</form>
{% endblock %}