Seite 1 von 1

Inhalt eines Formulares in eine Textdatei speichern/Captcha

Verfasst: Mittwoch 23. Januar 2008, 11:42
von Sonic
Hallo,

ich habe mir mit Python eine Datei erstellt, die die Benutzereingabe eines html Formulars anzeigt. Nun würde ich das ganze gerne erweitern, und zwar sollte auf die Seite noch ein Ok Button zur bestätigung der Eingabe. Beim Klick auf den Button sollten die Informationen in eine .txt Datei geschrieben werden, die dann bei jeder neuen Eingabe einfach die Daten der nächsten Person anhängt(also nicht für jede Person eine neue Datei).

Dann würde ich in das Formular gerne noch ein Captcha einbauen.
Es sollte jedem User ein neue Session zuweisen, damit keiner eine Fehlermeldung bekommt)

Ich hoffe, ihr habt das einigermaßen verstanden und könnt mir vielleicht sogar helfen :D

Ach ja, falls ihr den Code braucht.

Code: Alles auswählen

#!/usr/local/bin/python2.3

import cgi
form=cgi.FieldStorage()

out = ""
print "Content-Type: text/html\n\n"
vorname = form["vorname"].value
name = form["nachname"].value
mail = form["mail"].value
zahlungsart = form["zahlungsart"].value
iq = form["iq"].value
alter = form["alter"].value
user_eingabe = form["user_eingabe"].value


out = out + "Vorname: " + vorname + "<br>" + "Nachname: " + name + "<br>" + "E-Mail: " + mail + "<br>" + "Zahlungsart: " + zahlungsart + "<br>" + "IQ: " + iq + "<br>" + "Alter: " + alter + "<br>" + "user_eingabe: " + user_eingabe  
print out

Verfasst: Mittwoch 23. Januar 2008, 14:02
von keppla
Zunächst der Standardtip: nutze WSGI, nicht pures CGI. Wsgi kann über CGI eingebunden werden, und es ist nicht so masochistisch zu Programmieren. Ich würde als einstieg "Werkzeug" empfehlen.

Zur Problematik:
ein Ok Button zur bestätigung der Eingabe
Das ist eher ne HTML-Frage, buttons machst du mit "<input type='submit' value='Ok!' />" oder "<button type='submit'>Ok!</button>", die innerhalb eines "<form>"-tags liegen.
Allerdings vermute ich, dass du was anderes Fragen willst, denn ich sehe nicht, wie die Werte überhaupt in die applikation kommen sollen, ohne Formular.
Dann würde ich in das Formular gerne noch ein Captcha einbauen.
Sofern das nicht nur für den Ehrgeiz ist: ein statisches Bild mit einem Text scheint für 99% aller Fälle zu genügen, sie codinghorror.com (hat immer "Orange") für ein prominentes Beispiel.

Verfasst: Mittwoch 23. Januar 2008, 14:36
von Sonic
Erstmal danke für die Tipps. :D
Das Formular dient nur als Vorlage, die Felder werden später noch geändert.

Code: Alles auswählen

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
       "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Formular</title>
</head>
<body>

<h1>Kontakt</h1>

<form method="get" action="/cgi-bin/ausgabe.py">
  <table border="0" cellpadding="0" cellspacing="4">
    <tr>
      <td align="right">Vorname:</td>
      <td><input name="vorname" type="text" size="30" maxlength="30"></td>
    </tr>
    <tr>
      <td align="right">Nachname:</td>
      <td><input name="nachname" type="text" size="30" maxlength="40"></td>
    </tr>
    <tr>
      <td align="right">E-Mail:</td>
      <td><input name="mail" type="text" size="30" maxlength="40"></td>
    </tr>
    <tr>
      <td align="right">Zahlmethode:</td>
      <td><input type="radio" name="zahlungsart" value="Mastercard"> Mastercard<br>
    	  <input type="radio" name="zahlungsart" value="Visa"> Visa<br>
    	  <input type="radio" name="zahlungsart" value="AmericanExpress"> American Express</td>
    </tr>
    <tr>
       <td align="right">IQ:</td>
       <td><input type="checkbox" name="iq" value="u50"> Unter 50<br>
    	   <input type="checkbox" name="iq" value="51-199"> 51-199<br>
    	   <input type="checkbox" name="iq" value="ü200"> Über 200</td>
    </tr>
    <tr>
      <td align="right">Alter:</td>
      <td><select name="alter" size="5">
      <option value="u18">Unter 18</option>
      <option value="18-25">18-25</option>
      <option value="26-40">26-40</option>
      <option value="41-60">41-60</option>
      <option value="ü60">Über 60</option>
    </select></td>
    </tr>
    <tr>
      <td align="right">Kommentar:</td>
      <td><textarea name="user_eingabe" cols="50" rows="10"></textarea></td>
    </tr>
    <tr>
      <td align="right"></td>
      <td><input type="submit" value="Absenden"><input type="reset" value="Löschen"></td>
    </tr>
  </table>

    
  
</form>
</body>
</html>


Wenn man auf den absenden Button klickt, ruft er die .py datei auf, die dann die Eingaben anzeigt. Den bestätigungsbutton müsste ich dann in die .py Datei irgendwie einbinden.

Das mit dem captcha ist nicht nur für den Ehrgeiz :)
Das mit dem statischen Bild ist gar keine schlechte Idee, werde ich gleich mal ausprobieren :wink:

Kannst du mir vielleicht einen kleinen Tipp geben, wie ich ihm sage das er die Daten die er anzeigt in eine txt Datei packen soll?
Habe erst vor ein paar Tagen mit Python angefangen, schon mehrere Stunden danach gegooglet, mir fällt einfach nichts ein wie ich das machen könnte.

Verfasst: Mittwoch 23. Januar 2008, 15:22
von keppla
Das mit dem captcha ist nicht nur für den Ehrgeiz :)
Das mit dem statischen Bild ist gar keine schlechte Idee, werde ich gleich mal ausprobieren :wink:
Bei einer von "meinen" Seiten hats gereicht. Ich war überrascht, in einem selbstgeschriebenen Gästebuch auf einmal Spam vorzufinden (scheinen ja schon etwas heller geworden zu sein, die Bots).
Statisches Bild mit Text, immer gleiche Eingabe, und gut war. Keinen Spam seitdem.
Kannst du mir vielleicht einen kleinen Tipp geben, wie ich ihm sage das er die Daten die er anzeigt in eine txt Datei packen soll?
Da gibts mehrere Möglichkeiten, abhängig davon, was genau die Anforderung ist.

1. Du willst die Daten eigentlich nur speichern, nur dein Programm liest sie wieder

Da würde sich dann "pickle" anbieten, dass erlaubt, Pythonobjekte wie dicts, listen, tupel, etc in eine Datei zu speichern bzw aus ihr zu holen, ohne über das Format nachdenken zu müssen. Sehr bequem, die Textdateien sind aber nicht Menschenlesbar.

Oder, je nachdem wie groß die Applikation wird, speicher den Krams in einer Datenbank. Solange sich kein eigene DB-Server lohnt, gibt es SQLite, was sich so verhält, als wäre es eine DB, aber im Endeffekt nur ne datei ist (vergleichbar mit den MS-Access-Dateien), wenn er lohnt wären da MySQL und Postgres die nächsten Schritte.
Je nach "Eskalationsgrad" kann sich SQL-Alchemy lohnen, was eine Bibliothek ist, mit der man Plattform- und Datenbankunabhängig Datenbanken nutzen kann.

2. Du willst wirklich eine Textdatei speichern, und sie muss in einem bestimmten Format sein, was andere Menschen oder Programme lesen können sollen.

In diesem Fall müsstest du einen Exporter schreiben. Wie man das macht, hängt vom Datenformat ab.
Je nach angepeilter Professionalität ist das allerdings nicht gerade Trivial, schnell können da viele der Probleme auftreten, die Datenbanken lösen sollen (concurrency, z.B.)

Verfasst: Mittwoch 23. Januar 2008, 16:01
von sma
Ein sehr einfaches "Captcha" kannst du dir so bauen:

Wähle zwei Zufallszahlen zwischen 1 und 9.

Füge dann einen HTML- (oder JavaScript)-Schnipsel in dein Formular ein, der dem User die Frage nach der Summe der beiden Zahlen stellt.

Damit du prüfen kannst, ob der Benutzer die korrekte Antwort beim Absenden des Formulars gegeben hat, musst du natürlich selbst die Antwort kennen. Um keine Session auf dem Server zu verwalten, überträgst du am besten die korrekte Antwort ebenfalls.

Code: Alles auswählen

<form ...>
  <input type="hidden" name="a" value="MTM="/>
  6 + 7 = <input type="text" name="b" value=""/>
  ...
</form>
Damit man diese jetzt nicht einfach auslesen kann, verschlüsselst du sie.

Leider kommt Python nicht mit mit adäquaten Kryptografie-Funktionen, somit musst du improvisieren. Möglicherweise reicht encode('base64').

Oder du sagst, die Antwort soll immer 8 lauten und variierst einfach die Eingabe, also eine zufällige Zahl zwischen 1 und 7 und eine zwischen 1 und 8 minus erste Zahl. Ist aber ein bisschen sehr dünn.

Daher vielleicht lieber selbst eine schäbige Verschlüsselungsfunktion gebaut:

Code: Alles auswählen

def encrypt(n, k):
    return xor(str(randint(100, 999) * 19 + n), k).encode("hex")

def decrypt(s, k):
    return int(xor(s.decode("hex"), k)) % 19

def xor(s, k):
    k = k * (len(s) / len(k) + 1)
    return "".join(chr(ord(sc) ^ ord(kc)) for sc, kc in zip(s, k))
Stefan

Verfasst: Mittwoch 23. Januar 2008, 16:28
von Sonic
Vielen Dank für eure Vorschläge, werde mir überlegen was besser passt.

Verfasst: Mittwoch 23. Januar 2008, 20:59
von keppla
Ist jetzt eher eine Akademische Diskussion, wie gesagt reichen statische Bilder imho, aber...
sma hat geschrieben:Damit du prüfen kannst, ob der Benutzer die korrekte Antwort beim Absenden des Formulars gegeben hat, musst du natürlich selbst die Antwort kennen. Um keine Session auf dem Server zu verwalten, überträgst du am besten die korrekte Antwort ebenfalls.
Womit du auf eine recht komplizierte Art ziemlich genau das erreicht hat, was ein statisches Bild leistet, aber nicht mehr.
Beim statischen Bild muss der Angreifer einmal die Seite angucken, das Wort merken, und kann dann immer das gleiche senden.

Bei deiner Lösung muss er sich nur eine passende verschlüsselte Antwort/Antwort-kombination merken, und kann fortan die immer Senden.

Das ganze bietet keinerlei Mehrwert, nur deutlich mehr Arbeit.

Anders sähe das aus, wenn du die Lösung nicht auf der Webseite (egal ob offen oder kryptographisch sicher verschlüsselst), sondern Serverseitig, in einer Session oder sonstwie mitschleppst.

Im Endeffekt dürfte es allerdings auch nicht mehr lange hin sein, bis die Spambots eine höhere Trefferquote haben als die Menschen, da sowohl die User immer blöder als auch die Spammer immer schlauer werden.

Verfasst: Mittwoch 23. Januar 2008, 23:07
von sma
keppla hat geschrieben:[...]Womit du auf eine recht komplizierte Art ziemlich genau das erreicht hat, was ein statisches Bild leistet, aber nicht mehr.
Das sehe ich anders. Unter einem statischen Bild verstehe ich, dass bei jedem Formular das selbe Bild präsentiert wird, damit bei jedem Request die selbe Antwort erwartet wird. Damit muss der Spammer, das nur einmal herausbekommen und einfach diese Antwort bei jedem Request mitschicken. Damit ist das ein äußerst schwacher Schutz.

Meinen Vorschlag halte ich für besser. Ich verlange zumindest 18 verschiedene Antworten wobei nicht vorhersagbar ist, welche erwartet wird.

Natürlich kann man hier durch das Parsen des HTML-Quelltexts die Antwort ableiten, wenn man die Frage direkt ins HTML kodiert. Benutzt man JavaScript, muss der Spammer einen Browser fernsteuern und kann nicht mehr mit einem einfachen Kommandozeilen-Script arbeiten. Natürlich alles nichts, was einem ernsthaften Versuch standhält, aber besser, als eine feste Antwort.

Das ist für mich ein Mehrwert.

Statt deines Bildes, was vielleicht nicht jeder erkennen kann, kannst du auch sagen:

Code: Alles auswählen

<form ...>
  Gibt hier 42 ein:<input type="text" name="a"/>
  ...
</form>
was exakt den selben Effekt hat.
keppla hat geschrieben:Anders sähe das aus, wenn du die Lösung nicht auf der Webseite (egal ob offen oder kryptographisch sicher verschlüsselst), sondern Serverseitig, in einer Session oder sonstwie mitschleppst.
Nein, das ist kein wesentlicher Unterschied. Eine vernünftige Verschlüsselung vorausgesetzt, ist diese mit vertretbarem Aufwand nicht zu überwinden. Client-seitige Sessions - nichts anderes habe ich hier - sind hier praktisch gleichwertig zu Server-seitigen Sessions, die deutlich aufwendiger zu implementieren wären.

Problem meines Verfahrens ist, dass es nur 18 mögliche Antworten gibt. Der Spammer kann damit einfach 18 Antworten schicken - 17 werden verworfen, doch eine kommt durch. Dafür spare ich mir den Aufwand, eines dieser komischen Bilder zu erzeugen, die man häufig nicht lesen kann und habe eine Lösung, die auch Blinde überwinden können.

Stefan

Verfasst: Donnerstag 24. Januar 2008, 08:53
von keppla
sma hat geschrieben:
keppla hat geschrieben:[...]Womit du auf eine recht komplizierte Art ziemlich genau das erreicht hat, was ein statisches Bild leistet, aber nicht mehr.
Das sehe ich anders. Unter einem statischen Bild verstehe ich, dass bei jedem Formular das selbe Bild präsentiert wird, damit bei jedem Request die selbe Antwort erwartet wird.
Ja, so meinte ich das auch.
Damit muss der Spammer, das nur einmal herausbekommen und einfach diese Antwort bei jedem Request mitschicken. Damit ist das ein äußerst schwacher Schutz.
Ja, aber eben nicht schwächer als dein Vorschlag, denn...
Meinen Vorschlag halte ich für besser. Ich verlange zumindest 18 verschiedene Antworten wobei nicht vorhersagbar ist, welche erwartet wird.
Du musst doch gar nicht vorhersagen, welche erwartet ist. Du kannst immer die selbe verschlüsselte Antwort/Antwort-kombo senden. Also die, die du beim ersten mal siehst, genau so wie beim Bild.
Problem meines Verfahrens ist, dass es nur 18 mögliche Antworten gibt.
Nein, das "Problem" dieses Verfahrens ist, das die Kenntnis von nur einer Antwort völlig ausreicht (also wie beim Bild) , egal wieviele Mögliche es gibt.

Verfasst: Donnerstag 24. Januar 2008, 09:35
von Sonic
edit/ hat sich erledigt, ich soll das Formular jetzt als .py Datei machen :roll: .

Verfasst: Donnerstag 24. Januar 2008, 11:37
von Sonic
Nächste Frage :roll: .
Ich habe das ganze jetzt mal angefangen und wollte wissen ob man die Checkboxen und Radiobuttons auch in Python umsetzen kann.
Die Eingabe funktioniert perfekt, nur wird nichts von beidem Ausgegeben.
Denke aber eher das ich irgendeinen dummen Fehler gemacht habe.

Code: Alles auswählen

#!/usr/local/bin/python2.3

import cgitb; cgitb.enable()
import cgi
form=cgi.FieldStorage()
print "Content-Type: text/html\n"
print "<HTML><HEAD><TITLE>Formular</TITLE></HEAD><BODY>"
if form.has_key("Send"):
  if form.has_key("Vorname"):
    print 'Vorname: ' + form["Vorname"].value + '<br>'
  if form.has_key("Nachname"):
    print 'Nachname: ' + form["Nachname"].value + '<br>'
  if form.has_key("mail"):
    print 'E-Mail: ' + form["mail"].value + '<br>'
  if form.has_key("Zahlungsart"):
      print 'Zahlungsart: ' + form["Zahlungsart"].value + '<br>'
  if form.has_key("IQ"):
      print 'IQ: ' + form["iq"].value + '<br>'
else:
  print '<FORM method="post" action="hallo.py">'
  print 'Vorname: <INPUT type="text" name="Vorname"><br>'
  print 'Nachname: <INPUT type="text" name="Nachname"><br>'
  print 'E-Mail: <INPUT type="text" name="mail"><br>'
  print 'Zahlungsart: <br>'
  print 'Mastercard:<INPUT type="radio" name"Zahlungsart" value="Mastercard"><br>Visa:<INPUT type="radio" name"Zahlungsart" value="Visa"><br>American Express:<INPUT type="radio" name"Zahlungsart" value="American Express"><br>'
  print 'IQ: <br>'
  print 'Unter 50 <INPUT type="checkbox" name="iq" value="u50"><br>51-199<INPUT type="checkbox" name="iq" value="51-199"><br>Über50<INPUT type="checkbox" name="iq" value="ü50"><br>'
  print '<INPUT type="submit" value="Absenden" name="Send">'
  print '</FORM>'
print "</BODY></HTML>"

Verfasst: Donnerstag 24. Januar 2008, 11:53
von keppla
Sonic hat geschrieben:Nächste Frage :roll: .
Ich habe das ganze jetzt mal angefangen und wollte wissen ob man die Checkboxen und Radiobuttons auch in Python umsetzen kann.
Warum sollte das etwas mit python zu tun haben?
Denke aber eher das ich irgendeinen dummen Fehler gemacht habe.
Ich denke auch, guck dir mal das "name"-tag genau an:

Code: Alles auswählen

<INPUT type="radio" name"Zahlungsart" value="Visa"><br>American Express:<INPUT type="radio" name"Zahlungsart" value="American Express"><br>
Und nochmal der ernstgemeinte Tipp: nutze WSGI! nutze Templates! egal was, kriech doch nicht so auf dem Zahnfleisch herum und produziere unwartbaren code (das Tag wäre dir mit jedem synatxhiliter aufgefallen, hättest du templates genutzt)

@edit
ich soll das Formular jetzt als .py machen
Sofern das Hausaufgaben oder was ähnliches sind, verstehe ich natürlich, dass der Tipp ins leere läuft, da du dir das nicht aussuchen kannst. Ansonsten aber bleibe ich dabei ;)

Verfasst: Donnerstag 24. Januar 2008, 12:28
von Sonic

Code: Alles auswählen

<INPUT type="radio" name"Zahlungsart" value="Visa"><br>American Express:<INPUT type="radio" name"Zahlungsart" value="American Express"><br>
Habe ich vollkommen übersehen.

Sofern das Hausaufgaben oder was ähnliches sind, verstehe ich natürlich, dass der Tipp ins leere läuft, da du dir das nicht aussuchen kannst. Ansonsten aber bleibe ich dabei Wink
Nicht direkt, bin in einem Praktikum und soll das ganze für den Betrieb machen, sozusagen als Übung. Da kann ich mir leider nicht aussuchen wie ich das machen will^^.
Sonst hätte ich das sofort ausprobiert, genauso wie pickle, was zu umständlich sein soll.

Verfasst: Donnerstag 24. Januar 2008, 13:06
von mkesper
Sonic hat geschrieben:Nicht direkt, bin in einem Praktikum und soll das ganze für den Betrieb machen.
O weia!

Verfasst: Donnerstag 24. Januar 2008, 13:30
von keppla
Nicht direkt, bin in einem Praktikum und soll das ganze für den Betrieb machen, sozusagen als Übung. Da kann ich mir leider nicht aussuchen wie ich das machen will^^.

Sonst hätte ich das sofort ausprobiert, genauso wie pickle, was zu umständlich sein soll.
Picklen ist eine Zeile. Textdatei schreiben und lesen ist ein größerer Aufwand.
WSGI ist nicht komplizierter als cgi, es ist aber ein Standard mit vielen anderen Vorteilen.

Sollte das ein Praktikum bei einem Softwarehaus sein, nimm die besser nicht als Arbeitgeber.
Wenn die das Produktiv einsetzen wollen, und es nicht nur Übung ist, wäre das schon eine Form ausgleichender Gerechtigkeit, da du es nur einmal schreibst, die es aber Jahrelang warten müssen :)

Verfasst: Freitag 25. Januar 2008, 12:51
von EyDu
Wenn du dir um die Captchas keine Gedanken machen willst, kann ich nur reCAPTCHA empfehlen. Viel einfacher uns besser als sich selber etwas ausdenken.

Verfasst: Freitag 25. Januar 2008, 13:14
von Sonic
Gute Idee, aber leider mit copyright^^
Ich muss es jetzt doch dynmaisch machen, statisch reicht nicht :roll:
Bin für alle Tipps offen :P

Verfasst: Freitag 25. Januar 2008, 13:16
von gerold
Hallo!

Ich halte Captchas per Webservice für sehr bedenklich. Erst recht, wenn ich keinen persönlichen Kontakt zum Anbieter habe. Jeder Spammer kann sich so einen Dienst schreiben und anbieten. Er muss es nur verstehen, sich hinter anerkannten Institutionen zu verstecken.

Statt dem Kunden ein selbst generiertes Captcha anzubieten, wird ein Captcha einer anderen Website weitergereicht. So wird es dann z.B. auch möglich, automatisiert Einträge in Captcha-geschützten Gästebüchern zu hinterlegen. Und das, ohne die Bildchen selbst entschlüsseln zu müssen.

Damit möchte ich NICHT behaupten, dass reCaptcha unseriös sei. Ich glaube sogar, dass reCaptcha seriös sein könnte. Aber meine Bedenken gegenüber so einem Webservice wollte ich euch nicht vorenthalten.

mfg
Gerold
:-)

Verfasst: Freitag 25. Januar 2008, 13:56
von sma
keppla hat geschrieben:Du musst doch gar nicht vorhersagen, welche erwartet ist. Du kannst immer die selbe verschlüsselte Antwort/Antwort-kombo senden.
Da hast du natürlich Recht - ich war blind...

Stefan