667
24.6
Online-Redaktionssystem mit Datenbankanbindung
Abb. 24.9: Aus dem MD5-Fingerprint kann das Passwort (in vernünftiger Rechenzeit) nicht
wiedergewonnen werden.
Das Python-Modul hashlib enthält eine Implementierung des MD5-Algorithmus. Durch
einen Aufruf von
md5(b) wird ein neues md5-Objekt zum Bytestring b erzeugt. Ein regulärer
String muss also zuerst (mithilfe einer Codierung) in einen Bytestring überführt werden.
Durch einen Aufruf der Methode
digest() wird ein Fingerprint aus 16 Zahlen berechnet.
Beispiel:
Der Fingerprint ist ein Bytestring der Länge 16, also letztlich eine Folge von 16 Zahlen zwi-
schen 0 und 255.
24.6.4 Implementierung des Redaktionssystems mit Python (OOP)
Interaktives Skript für den Administrator
Das folgende Skript realisiert auf einfache Weise die Geschäftsprozesse »Benutzer einrich-
ten« und »neue Datenbank einrichten«. Es muss so gespeichert werden, dass nur der Admi-
nistrator des Redaktionssystems ein Zugriffsrecht hat. Das Skript initialisiert außerdem
zwei Datenbank-Dateien für die Passwörter der Redakteure und die Beiträge eines Online-
Journals, sofern diese Dateien noch nicht vorhanden sind. Der Administrator gibt bei der
Anlage eines neuen Accounts nur einen Benutzernamen ein. Das Passwort wird automa-
tisch erzeugt. (Es ist gleich dem Benutzernamen.)
Skript:
>>> from hashlib import md5
>>> m = md5("Dies ist ein geheimer Text".encode("utf-8"))
>>> m.digest()
b'\x8c\x1c\xc4+]2\x08\xc1y\nC\xc6\x90\xff+\xa5'
#admin.py
import sqlite3,hashlib
class Admin(object):
def __init__(self, db_pfad):
verbindung = sqlite3.connect(db_pfad)
praktisch nicht
berechenbar
md
5
passwort
fingerprint
geheim
öffentlich
Kapitel 24
Datenbanken
668
c = verbindung.cursor()
try:
c.execute("SELECT * FROM person") #1
c.execute("SELECT * FROM beitrag")
except:
# Tabellen existieren noch nicht
c.execute("""CREATE TABLE
person(name VARCHAR(50),
f ing e rpri n t BI N ARY ( 1 6))
"" " ) #2
c.execute("""CREATE TABLE
beitrag(titel VARCHAR(100),
tex t V ARC H AR( 1 000 ) ,
ver f a lls d atu m FLO A T ,
aut o r VAR C HAR ( 50) ) ;
" "")
v e rbin d ung . c o mmi t () #3
print('Liste der User-Namen:')
c.execute("SELECT * FROM person")
for zeile in c: print(zeile[0])
neu = input('Neuer User (Ende mit ENTER): ')
while neu:
if list(c.execute("""SELECT *
F ROM p erso n
WHERE name = ?;""", (neu,))):
print('Name existiert bereits.') #4
else:
m = hashlib.md5(neu.encode("utf-8"))
c.execute("""INSERT INTO person
VALUES(?, ?);""",
(ne u , m.d i ges t ()) ) #5
v e rbin d ung . c o mmi t ()
neu = input('Neuer User (Ende mit ENTER): ') #6
print('Datenbank wurde aktualisiert.')
c.close()
verbindung.close()
Admin('redaktion.db')
669
24.6
Online-Redaktionssystem mit Datenbankanbindung
Erläuterung:
#1: Versuche, aus den beiden Tabellen Daten zu lesen.
#2: Falls der Versuch misslingt, werden die Tabellen angelegt …
#3: … und in einer Datenbank-Datei gespeichert.
#4: Der Name ist ein Schlüsselattribut und muss deshalb einmalig sein.
#5: Wenn der vom Administrator eingegebene Name noch nicht existiert, werden Name und
Fingerprint des Namens in der Tabelle
person gespeichert. Der Name wird als vorläufiges
Passwort verwendet, das später vom Redakteur selbst geändert werden kann.
#6: An dieser Stelle muss die Einrückung genau stimmen, sonst riskieren Sie eine Endlos-
schleife.
Beispielprogrammlauf:
Statische Webseite für das Login des Redakteurs
Der folgende HTML-Quelltext beschreibt die Webseite, die von einem Redakteur aufgerufen
wird, wenn er sich einloggen will (siehe Abbildung 24.4). Nach dem Anklicken des Submit-
Buttons wird das CGI-Skript für den Redakteur aufgerufen. In dem Beispiel gehen wir
davon aus, dass dieses CGI-Skript unter der Kontrolle eines lokalen HTTP-Servers (local-
host) steht.
Liste der User-Namen:
Michael Klein
Melanie Beck
Tom Specht
Neuer User: Kim Hensing
Neuer User:
Datenbank wurde aktualisiert.
<html>
<head>
<title>Python-Redaktionssystem</title>
<meta http-equiv="Content-Type" content="charset=utf-8" />
</head>
<body bgcolor=#C0C0C0>
<h2> Python-Redaktionssystem</h2>
<form action="http://localhost:8000/cgi-bin/redaktion.py"
method="POST">
Name: <input type="Text" name="name" >&nbsp;
Passwort: <input type="Password" name="passwort"><br><br>
<input type="Submit" value="Login">
</form></body>
</html>
Kapitel 24
Datenbanken
670
CGI-Skript für den Redakteur
Skript:
#! /Python35/python.exe
#----------------------------------------------------
# Dateiname: redaktion.py
#
# Das CGI-Skript verarbeitet folgende Variablen,
# die vom aufrufenden Client gesendet werden:
# name, passwort, neuespass, neupass1, neupass2
# titel, text, haltbar (Anzahl der Tage)
#
#----------------------------------------------------
import sqlite3, cgi, hashlib, cgitb, time, logging
cgitb.enable()
logging.basicConfig(filename="logging.txt",
format="%(funcName)s: %(message)s",
level=logging.DEBUG,
fi l emo d e = "w" ) #1
# Schablone für HTTP-Paket
SEITE1 = """Content-type: text/html
<html>
<head>
<title>Python-Redaktionssystem</title>
<meta http-equiv="Content-Type" content="charset=utf-8" />
</head>
<body bgcolor=#C0C0C0>
<h2>Python-Redaktionssystem</h2>
<form action="http://localhost:8000/cgi-bin/redaktion.py"
method="POST" >
<input type="hidden" name="name" value="{}">
<input type="hidden" name="passwort" value="{}">
<b>Titel: </b><input type="Text" name="titel"
size="50" maxlength="80"><br><br>
<textarea name="text" cols="50" rows="8" >{}
</textarea><br>
<h4>Haltbarkeit</h4>
<input type="Radio" name="haltbar" value="14"
checked="checked">
2 Wochen <br>
671
24.6
Online-Redaktionssystem mit Datenbankanbindung
<input type="Radio" name="haltbar" value="30">
1 Monat <br>
<input type="Radio" name="haltbar" value="90">
3 Monate <br>
<input type="Radio" name="haltbar" value="180">
6 Monate <br>
<h4> Passwortverwaltung</h4>
<input type="Checkbox" name="neuespass" value="1">
Passwort &auml;ndern<br>
<input type="Password" name="neupass1" > Neues Passwort<br>
<input type="Password" name="neupass2" > Passwort wiederholen<br>
<input type="Submit" value="Absenden">
</form>
<i>{}<br>{}<br></i>
</body></html>"""
# HTTP-Paket mit Fehlermeldung bei falschem Login
SEITE2 = """Content-type: text/html
<html>
<head><title>Python-Redaktionssystem</title>
<meta http-equiv="Content-Type" content="charset=UTF-8" />
</head>
<body bgcolor=#C0C0C0>
<h2> Python-Redaktionssystem</h2>
<form action="http://localhost:8000/cgi-bin/redaktion.py"
method="POST">
Name: <input type="Text" name="name" >&nbsp;
Passwort: <input type="Password"
name="passwort"><br><br>
<input type="Submit" value="Login">
</form>
<b> Login gescheitert! &Uuml;berpr&uuml;fen Sie Name und
Passwort.<b>
</body></html>"""
# Schablone für Webseite (Publikation)
# Platzhalter {}: Zeit und Beiträge
WEBSEITE = """<html>
<head><title>Python-News</title></head>
<body>
<h1>Python-News</h1>
Letzte &Auml;nderung: {}
{}

Get Python 3 - Lernen und professionell anwenden now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.