Galileo Computing < openbook >
Galileo Computing - Programming the Net
Galileo Computing - Programming the Net


Java ist auch eine Insel (2. Aufl.) von Christian Ullenboom
Programmieren für die Java 2-Plattform in der Version 1.4
Java ist auch eine Insel (2. Auflage)
gp Kapitel 4 Der Umgang mit Zeichenketten
  gp 4.1 Strings und deren Anwendung
  gp 4.2 Veränderbare Zeichenketten mit der Klasse StringBuffer
    gp 4.2.1 Anlegen von StringBuffer-Objekten
    gp 4.2.2 Die Länge eines StringBuffer-Objekts lesen und setzen
    gp 4.2.3 Daten anhängen
    gp 4.2.4 Zeichen(folgen) setzen, erfragen, löschen und umdrehen
  gp 4.3 Vergleiche von Zeichenketten als String und StringBuffer
    gp 4.3.1 Sollte es ein equals() und hash() bei StringBuffer geben?
  gp 4.4 Ein paar kleine Helfer
    gp 4.4.1 Strings einer gegebenen Länge erzeugen und rechtsbündig ausgeben
    gp 4.4.2 Teile im String ersetzen
  gp 4.5 Zeichenkodierungen umwandeln
  gp 4.6 Sprachabhängiges Vergleichen mit der Collator-Klasse
    gp 4.6.1 Effiziente interne Speicherung für die Sortierung
  gp 4.7 Die Klasse StringTokenizer
  gp 4.8 StreamTokenizer
  gp 4.9 Formatieren mit Format-Objekten
    gp 4.9.1 Prozente, Zahlen und Währungen ausgeben
    gp 4.9.2 Ausgaben formatieren
    gp 4.9.3 Dezimalzahlformatierung
  gp 4.10 Reguläre Ausdrücke
    gp 4.10.1 Splitten von Zeichenketten
    gp 4.10.2 split() in String
    gp 4.10.3 Das Paket gnu.regexp
  gp 4.11 Überprüfung der E-Mail-Adressen und Kreditkarteninformationen
    gp 4.11.1 Gültige E-Mail-Adressen
    gp 4.11.2 Kreditkartennummern testen


Galileo Computing

4.11 Überprüfung der E-Mail-Adressen und Kreditkarteninformationen  downtop


Galileo Computing

4.11.1 Gültige E-Mail-Adressen  downtop

Benutzer von Webseiten werden an vielen Stellen aufgefordert, ihre E-Mail-Adresse für Nachrichtenverteiler und Informationen einzutragen. Hier kommt es häufiger vor, dass Kunden nicht ihre richtige Adresse eintragen, sondern irgendwelchen Unsinn. Schlauerweise sollte man schon im Vorfeld grobe Fehler erkennen und abblocken. Bei konventionellen HTML-Seiten bieten sich hierfür JavaScript-Überprüfungen an. Wir wollen aber eine pure Java-Lösung vorstellen, die speziell für Servlets interessant ist.

Sehen wir uns die Elemente einer korrekten E-Mail-Adresse an: Spende@KuchenFuer Ulli.org. Wir haben einen Namen, der mindestens einen Buchstaben lang ist. Das heißt, das @-Zeichen darf nicht am Anfang stehen. Genauso gut muss eine Endung existieren. Daher darf der hinterste Punkt nicht an letzter Stelle auftauchen. Dann müssen wir noch testen, ob überhaupt eine Zeichenkette eingetragen ist, und ob mindestens ein Punkt hinter dem @-Zeichen steht. Folgendes Programm testet eine Eingabe entsprechend:

Listing 4.9   EmailChecker.java

class EMailChecker
{
  static boolean isValidEMail( String s )
  {
    s = s.trim();

     int at, dot, len = s.length();

    // s nicht angegeben (oder nur Whitespaces), oder kein @ bzw .

    if ( (len == 0) ||
         ((at=s.indexOf('@')) == -1) || ((dot=s.lastIndexOf('.')) == -1) )
      return false;

    // keine EMailadresse vor @ Zeichen oder . vor &

     if ( (at == 0) || (dot < at) )
      return false;

    // Mindestens zwei Zeichen für die Endung

    return dot+2 < len;
  }

  public static void main( String args[] )
  {
    System.out.println( isValidEMail("Ulli@Java-Tutor.com") );

    System.out.println( isValidEMail("  ") );
    System.out.println( isValidEMail("doofnase") );
    System.out.println( isValidEMail("@Java-Tutor.com") );
    System.out.println( isValidEMail("Ulli@Java-Tutor") );
    System.out.println( isValidEMail("Ulli@Java-Tutor.") );
  }
}

Eine intelligente Erweiterung wäre, die Endung mit allen möglichen Länderendungen (de, nl, tv ...) beziehungsweise Domain-Kennungen (com, net, org ...) zu validieren. Zusätzlich könnten wir versuchen, eine Verbindung zu dem angegebenen Server aufzubauen, um die Adresse zu testen. Wir könnten auch auf Namensdienste zurückgreifen und versuchen, herauszufinden, ob der Nutzer eingetragen ist. Denkbar ist auch eine Überprüfung in Newsgruppen, oder ob der Benutzer sich in auffälligen Foren bewegt und so weiter. Der Fantasie sind keine Grenzen gesetzt.


Galileo Computing

4.11.2 Kreditkartennummern testen  toptop

E-Commerce-Lösungen sind im Internet mittlerweile häufig anzutreffen. Lassen sich für kleine Beträge Sonderlösungen finden, werden für größere Beträge immer noch Kreditkarten verwendet. Grund genug für uns Java-Programmierer, die Nummern der Karten zu testen, um zu überprüfen, ob uns nicht ein Anwender täuschen wollte.

Die Nummer einer Kreditkarte setzt sich nicht willkürlich zusammen. Die Nummern von Karten eines bestimmten Herstellers bestehen aus einer festen Anzahl von meistens 14 bis 16 Ziffern. Als Kennung für einen Hersteller (Visa, MasterCard, American Express) ist jeder Nummer eine zusätzliche Kennung von einer bis vier Ziffern vorangestellt. Die Ziffern der Kartennummer werden durch mathematische Verfahren überprüft. Wir wollen eines dieser Verfahren auch kennen lernen; den so genannten Luhn-Algorithmus. Dieser Algorithmus testet die Korrektheit des Aufbaus einer Nummernfolge. Die letzte Ziffer ist oft eine berechnete Checksummen-Ziffer.

Die folgende Tabelle gibt eine Übersicht über einige Kartenhersteller. Sie führt die Kennung, die Länge der Kartennummer und ein gültiges Beispiel auf:

Tabelle 4.5   Kreditkartenhersteller und ihre Kennnummern
Hersteller Anfang Gesamtlänge Beispiel
Visa 4 13, 16 4111 1111 1111 1111
Master 51,52,53,54,55 16 5500 0000 0000 0004
Diner’s Club11  30,36,38 14 3000 0000 0000 04
American Express12  34, 37 15 3400 0000 0000 009
Discover 6011 16 6011 0000 0000 0004
en Route 2014, 2149 15 2014 0000 0000 009
JCB 3088,3096,3112,3158,3337,3528 16 3088 0000 0000 0009

Neben den Herstellernummern sind auch folgende Nummern von den ausgebenden Banken im Umlauf: Manufacturers Hanover Trust (1033), Citibank (1035), Chemical Bank (1263), Chase Manhattan (1665), Bank of America (4024), Citicorp (4128), New Era Bank (4209), HHBC (4302), Imperial Savings (4310), MBNA (4313), California Federal (4317), Wells Fargo (5282), Citibank (5424), Wells Fargo (5410), Bank of New York (5432), MBNA (6017). Carte Blanche und Diner’s Club haben die gleichen Nummern.

Die Überprüfung mit dem Luhn-Algorithmus

Der Luhn-Algorithmus (auch modulus 10 oder mod 10-Algorithmus genannt) basiert auf dem ANSI-Vorschlag X4.13. Er wurde Ende 1960 von einer Gruppe Mathematiker ausgearbeitet und veröffentlicht. Danach nutzten Kreditkartenhersteller dieses Verfahren zur Prüfung der Kreditkartennummern. Auch die Versichertennummer in Kanada, die Canadian Social Insurance Number (CSIN), wird über das Luhn-Verfahren geprüft.

Der Algorithmus testet, ob die letzte Ziffer der Kreditkartennummer korrekt zu den angegebenen Zahlen passt. Die Testziffer wird von allen Ziffern außer der letzten Ziffer berechnet und anschließend mit der angegebenen Testziffer verglichen. Stimmt sie überein, ist die Karte seitens der Prüfnummer in Ordnung. Wir wollen das Verfahren hier nicht näher vertiefen, sondern einfach den Algorithmus angeben:

Listing 4.10   LuhnTest.java

class LuhnTest
{
  static boolean luhnTest( String s )
  {
    int len = s.length();

    int digits[] = new int[len];

    for ( int i = 0; i < len; i++ )
    {
      try {
        digits[i] = Integer.parseInt( s.substring(i,i+1) );
      }
      catch ( NumberFormatException e ) {
        System.err.println( e );
        return false;
      }
    }

    int sum=0;

    while ( len > 0 )
    {
      sum += digits[len-1];
      len--;

      if ( len > 0 )
      {
        int digit = 2*digits[len-1];
        sum += ( digit>9) ? digit-9 : digit;

        len--;
      }
    }

    return ( sum%10 == 0 );
  }


  static boolean isVisa( String s )
  {
    if ( ( (s.length() == 16) || (s.length() == 13) ) &&
          (s.charAt(0) == '4') )
      return luhnTest( s );

    return false;
  }

  public static void main( String args[] )
  {
    System.out.println( luhnTest( "4111111111111111" ) );
    System.out.println( luhnTest( "5500000000000004" ) );
    System.out.println( luhnTest( "340000000000009" ) );
    System.out.println( luhnTest( "30000000000004" ) );
    System.out.println( luhnTest( "6011000000000004" ) );
    System.out.println( luhnTest( "201400000000009" ) );
    System.out.println( luhnTest( "3088000000000009" ) );
    System.out.println( luhnTest( "9238475098787444" ) );

    System.out.println( isVisa( "4111111111111111" ) );
    System.out.println( isVisa( "5500000000000004" ) );


    // Böse: Visa-Nummer generieren

    char c[] = "4123456789123456".toCharArray();

    while ( !isVisa(new String(c)) )
      c[(int)(Math.random()*c.length-1)+1] = (char)('0'+Math.random()*9.9);

    System.out.println( c );
  }
}

Im Quelltext ist eine zusätzliche Methode eingebaut, die testet, ob die Karte von Visa ist. Dazu müssen wir nur überprüfen, ob die erste Ziffer eine 4 und die gesamte Zahl nach dem Luhn-Verfahren gültig ist. Andere Tests sind genauso einfach durchzuführen. Eine mögliche Erweiterung wäre, die Methode fehlertoleranter zu gestalten, indem Trennzeichen herausgefiltert werden. Dies und die Implementierung der übrigen Tests überlasse ich als Übung den Lesern.

Wir beginnen mit einer vorgegebenen, unsinnigen Kartennummer, deren erste Stelle »4« ist, wie für eine Visa-Karte erforderlich. Anschließend ändern wir in einer Schleife eine zufällig ausgewählte Stelle der Kartennummer (außer der ersten) in eine ebenfalls zufällig bestimmte Ziffer aus dem Bereich »0« bis »9«. Das wiederholen wir so lange, bis die abgewandelte Zahl irgendwann passt.

Beispiel   Mit diesen Methoden ist es natürlich leicht möglich, Nummern zu erzeugen. Betrachten wir Folgendes:
char c[] = "4123456789123456".toCharArray();
while ( !isVisa(new String(c)) )
  c[(int)(Math.random()*c.length-1)+1] =
                            (char)('0'+Math.random()*9.9);

System.out.println( c );






1   Veni, Vidi, VISA: I came, I saw, I did a little shopping.

2   Einen Abend im Februar 1950 vergaß Frank MacNamara seine Brieftasche. Er kam auf die Idee, eine Kreditkarte aus Karton anzubieten. Mit seinen Freunden gründete er am 28.2.1950 den Diner's Club, der im Gründerjahr mehr als 10.000 Mitglieder und 1.000 Vertragspartner hatte. So war die erste Kreditkarte geboren.

3   Im Jahre 1958 entschloss sich das internationale Transport-, Reise-, und Finanzierungsunternehmen American Express, eine eigene Karte herauszugeben.





Copyright © Galileo Press GmbH 2003
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de