Chapter 11 ■ the World Wide Web
192
The schema is overly simple—the bare minimum needed to get this application running. In real life, there would
need to be a users’ table for usernames and secure password hashes, and an official table of bank accounts where
money could come from and be saved to. Instead of being realistic, this app allows the user to create example account
names as they type.
One key operation to study in this example is that all of the arguments to its SQL calls are properly escaped. A
major source of security flaws today is programmer failure to escape special characters properly when submitting
them to an interpreted language like SQL. What if a malicious user of your web front end thinks of a way to type the
memo field so that it includes special SQL code? The best protection is to rely on the database itself—and not your
own logic—to quote data properly.
Listing 11-1 does this correctly by giving SQLite a question mark (?) everywhere that the code wants a value
interpolated, instead of trying to do any escaping or interpolation of its own.
The other key operation is to mix down the raw database rows into something more semantic. The fetchall()
method is not unique to sqlite3 but is part of the DB-API 2.0 that all modern Python database connectors support for
interoperability. Moreover, it does not return an object, or even a dictionary, for each row that comes back from the
database. It returns a tuple for each returned row.
(1, 'brandon', 'psf', 125, 'Registration for PyCon')
The result of handling these raw tuples could be unfortunate. Ideas in your code like “the account credited” or
“the number of dollars paid” might appear as row[2] or row[3] and be difficult to read. So, bank.py instead spins up
a quick named-tuple class that will also respond to attribute names such as row.credit and row.dollars. Creating
a new class each time SELECT is called is not optimal but provides the kind of semantics that web application code
needs in one or two quick lines of code—letting you more quickly turn to web application code itself.
A Terrible Web Application (in Flask)
In addition to reading the program listings that follow, you can experiment with the sample web applications in the
next several listings by checking out the source code repository for this chapter here:
https://github.com/brandon-rhodes/fopnp
You can browse the files specific to this chapter here:
https://github.com/brandon-rhodes/fopnp/tree/m/py3/chapter11
The first file you should study is app_insecure.py, which is shown in Listing 11-2. It is worth reading through the
code carefully before facing these questions: Does it look like the kind of terrible and untrustworthy code that results
in security compromises and public disgrace? Does it even look dangerous?
Listing 11-2. An Insecure Web Application (Not Flask’s Fault!)
#!/usr/bin/env python3
Foundations of Python Network Programming, Third Edition
https://github.com/brandon-rhodes/fopnp/blob/m/py3/chapter11/app_insecure.py
A poorly-written and profoundly insecure payments application.
(Not the fault of Flask, but of how we are choosing to use it!)
import bank
from flask import Flask, redirect, request, url_for
from jinja2 import Environment, PackageLoader