Login/Register mit "Passwort vergessen"-Funktion

Wichtiger Hinweis: Bitte ändert nicht manuell die Schriftfarbe auf schwarz sondern belasst es bei der Standardeinstellung. Somit tragt ihr dazu bei dass euer Text auch bei Verwendung unseren dunklen Forenstils noch lesbar ist!

Tipp: Ihr wollt längere Codeausschnitte oder Logfiles bereitstellen? Benutzt unseren eigenen PasteBin-Dienst Link
  • Hallo alle zusammen und Willkommen zu meinem 3. Tutorial.
    Hier möchte ich euch erklären, wie ihr ein auf Dialogen aufgebauetes Login-/Registersystem mit einer ingame Passwort-vergessen Funktion schreiben könnt.
    Ich weiß natürlich, dass es genug Tutorials zu dialogbezogenen Login-/Registersystemen auf Dini gibt, deshalb werde ich auf diese Punkte garnicht allzu viel näher eingehen, sondern eher das Hauptaugenmerk auf die eben angemerkte "Sonderfunktion" legen.


    Ablauf

    • Spieler registriert sich mit Passwort, geheimer Frage & geheimer Antwort.
    • Spieler vergisst sein Passwort und gibt ingame /passwortvergessen ein.
    • Spieler gibt die Antwort auf seine geheime Frage ein.
    • Wenn richtig wird ein neues Passwort (zufällig aus einer Liste vorgegebener Passwörter) erstellt und ihm zugewiesen.
    • Spieler kann sich mit diesem Passwort einloggen und danach mit /pwändern ein neues zuweisen.


    Dann fangen wir mal an. Das erste was wir benötigen sind die Defines der Dialoge- Nicht zu vergessen natürlich die implementierte Dini-Include, was ihr aber wissen solltet.
    #define login 1
    #define register1 2
    #define register2 3
    #define register3 4
    #define lostpw 5
    #define pwchange 6
    Kurze Erklärung: login ist unser Dialog für den Login. In register1 gibt man sein Passwort ein, in register2 kann man seine geheime Frage wählen und in register3 die Antwort dazu eintragen. lostpw ist natürlich dann der Dialog um die Antwort abzufragen. Und zu guter letzt kommt pwchange was den Dialog zum Ändern des Passwortes darstellt.


    Als nächstes wollen wir eine Liste mit Passwörtern erstellen, die dem Nutzer zufällig zugewiesen werden.
    new lostpws[][] =
    {
    "Ivamdub",
    "gimfves",
    "Fb53Ac",
    "Every90",
    "Deutschland",
    "Gefaafny",
    "Ftgenrl",
    "Oranan",
    "Lituania",
    "UwAff3",
    "fhhalc",
    "fhn76",
    "75hd",
    "a7jvjmz",
    "fsdhr"
    };
    In diesem Fall sind es 15 Passwörter. Diese Zahl müssen wir uns für später noch merken. Welche Passwörter ihr verwendet ist grundsätzlich egal, ich hab im Moment einfach mal ein paar Nonsense-Wörter eingetragen.


    Nun gehen wir zum Callback OnPlayerConnect, wo wir überprüfen ob der Spieler registriert ist und ihm dementsprechend schreiben ob er sich einloggen oder registrieren soll.
    new name[MAX_PLAYER_NAME], path[128];
    GetPlayerName(playerid, name, MAX_PLAYER_NAME);
    format(path, 128, "/spieler/%s.ini", name);
    if(dini_Exists(path)) SendClientMessage(playerid, COLOR_ORANGE, "Willkommen zurück! Logge dich bitte mit /login ein.");
    else SendClientMesssage(playerid, COLOR_ORANGE, "Willkommen auf unserem Server. Du bist noch nicht registriert. Erledige das bitte mit /register.");
    Das sollte es für den Moment tun. Zuerst erstellen wir den Pfad zur Spielerdatei im Userfiles-Ordner (Pfad auf jeden Fall erstellen. In diesem Fall den Ordner "spieler"!) und überprüfen dann ob eine Datei mit dem Namen des Spielers bereits existiert. Wenn ja, geben wir ihm die Nachricht zum einloggen, ansonsten zum registrieren. COLOR_ORANGE muss natürlich auch als solche definiert sein.


    Jetzt geht es zu den eigentlichen Commands unter OnPlayerCommandText.

    if (strcmp(cmd, "/login", true) == 0)
    {
    new name[MAX_PLAYER_NAME], path[128];
    GetPlayerName(playerid, name, MAX_PLAYER_NAME);
    format(path, 128, "/spieler/%s.ini", name);
    if(dini_Exists(path)) ShowPlayerDialog(playerid, login, DIALOG_STYLE_INPUT, "Bitte einloggen.", "Willkommen zurück auf unserem Server.\r\nBitte logge dich ein.", "Annehmen", "Abbrechen");
    else SendClientMessage(playerid, COLOR_RED, "Du bist noch nicht registriert. Bitte erledige das mit /register.");
    return 1;
    }


    if (strcmp(cmd, "/register", true) == 0)
    {
    new name[MAX_PLAYER_NAME], path[128];
    GetPlayerName(playerid, name, MAX_PLAYER_NAME);
    format(path, 128, "/spieler/%s.ini", name);
    if(!dini_Exists(path)) ShowPlayerDialog(playerid, register1, DIALOG_STYLE_INPUT, "Registrierung.", "Willkommen auf unserem Server.\r\nBitte gib hier dein gewünschtes Passwort ein (nachträglich änderbar).", "Weiter", "Abbrechen");
    else SendClientMessage(playerid, COLOR_RED, "Du bist bereits registriert. Bitte logge dich mit /login ein");
    return 1;
    }


    if (strcmp(cmd, "/pwändern", true) == 0)
    {
    if(GetPVarInt(playerid, "loggedin") == 1)
    {
    ShowPlayerDialog(playerid, pwchange, DIALOG_STYLE_INPUT, "Passwort ändern", "Bitte gebe hier dein gewünschtes neues Passwort ein.", "Annehmen", "Abbrechen");
    }
    else SendClientMessage(playerid, COLOR_RED, "Du bist nicht eingeloggt.");
    return 1;
    }

    Wie ihr seht habe ich gleich alle 3 Commands die wir brauchen werden eingetragen. Kurze Erklärung zu den einzelnen:
    /login - Der Pfad der Spielerdatei wird gesucht. Wenn er existiert, wird der Dialog zum Login aufgerufen, ansonsten der Verweis auf /register.
    /register - Der Pfad der Spielerdatei wird gesucht. Wenn er nicht existiert, wird der Dialog zum Register aufgerufen, ansonsten der Verweis auf /login.
    /pwändern - Es wird überprüft ob der Spieler eingeloggt ist (Durch PVar, welche später beim Login gesetzt wird). Wenn dem so ist, wird der Login zum Passwortändern aufgerufen.


    Das war es zum leichten Teil. Nun kommen die Dialogabfragen. Anfangen tun wir diesmal auch mit dem Login. Wir setzen den Code in OnDialogResponse.

    new name[MAX_PLAYER_NAME], path[128];
    GetPlayerName(playerid, name, MAX_PLAYER_NAME];
    format(path, 128, "/spieler/%s.ini", name);
    if(dialogid == login && response)
    {
    new pw[256];
    pw = dini_Get(path, "PW");
    if(strcmp(pw, inputtext)) SendClientMessage(playerid, COLOR_RED, "Das eingegebene Passwort ist falsch.");
    else
    {
    SetPVarInt(playerid, "loggedin", 1);
    // Was immer nun passieren soll
    }
    return 1;
    }
    Da wir den Pfad der Spielerdatei nun öfter benutzen, schreibe ich ihn nicht jedes Mal neu, sondern einfach lokal für das gesamte Callback.
    Eigentlich ganz leicht. Zuerst überprüfen wir ob die Dialogid Login ist und eine Antwort (Button "Akzeptieren" gedrückt) gegeben wurde. Danach holen wir uns das Passwort des Spielers aus der Dini-Datei und speichern es in der Variable pw. Wenn pw und der eingegebene Text nicht gleich sind, wird die Nachricht gesendet, ansonsten wird die PVar "loggedin" auf 1 gesetzt und ihr könnt tun was immer ihr nun tun möchtet.


    Jetzt zu den einzelnen register-Dialogen, welche auch in OnDialogResponse gesetzt werden.
    if(dialogid == register1 && response)
    {
    dini_Create(path);
    dini_Set(path, "PW", inputtext);
    ShowPlayerDialog(playerid, register2, DIALOG_STYLE_LIST, "Geheime Frage auswählen", "Wie ist der Name deiner Mutter?\r\nWie heißt dein Haustier?\r\nWo bist du geboren?", "Weiter", "Abbrechen");
    return 1;
    }


    if(dialogid == register2)
    {
    if(!response) dini_Remove(path);
    else
    {
    switch(listitem)
    {
    case 0:
    {
    dini_Set(path, "Frage", "Mutter");
    ShowPlayerDialog(playerid, register3, DIALOG_STYLE_INPUT, "Geheime Frage beatnworten", "Bitte beantworte nun, wie deine Mutter heißt.", "Akzeptieren", "Abbrechen");
    }
    case 1:
    {
    dini_Set(path, "Frage", "Haustier");
    ShowPlayerDialog(playerid, register3, DIALOG_STYLE_INPUT, "Geheime Frage beatnworten", "Bitte beantworte nun, wie dein Haustier heißt.", "Akzeptieren", "Abbrechen");
    }
    case 2:
    {
    dini_Set(path, "Frage", "Geburtsort");
    ShowPlayerDialog(playerid, register3, DIALOG_STYLE_INPUT, "Geheime Frage beatnworten", "Bitte beantworte nun, was dein Geburtsort ist.", "Akzeptieren", "Abbrechen");
    }
    }
    }
    return 1;
    }


    if(dialogid == register3)
    {
    if(!response) dini_Remove(path);
    else
    {
    dini_Set(path, "Antwort", inputtext);
    SendClientMessage(playerid, COLOR_GREEN, "Herzlichen Glückwunsch! Du bist nun erfolgreich auf unserem Server registriert.");
    }
    return 1;
    }
    Das sieht auf den ersten Blick vielleicht etwas wirr aus, ist aber eigentlich ganz einfach. Im ersten Teil (register1) wird die Dini-Datei erstellt und das eingegebene Passwort dort hinein geschrieben. Danach wird der Dialog register2 als ListBox geöffnet, in dem man seine geheime Frage auswählen kann (Momentan Name der Mutter, - des Haustieres und Geburtsort, natürlich beliebig erweiterbar).
    Wenn dieser abgebrochen wird, wird die Dini wieder gelöscht, ansonsten wird durch einen switch die Frage (oder zumindest eine Kurzform davon) in die Dini gespeichert und gleichzeitig der neue Dialog gestartet.
    Wenn dieser abgebrochen wird, wird die Dini natürlich auch wieder gelöscht. Falls nicht, wird die Antwort auch in die Dini geschrieben und die Nachricht, dass man nun erfolgreich registriert ist, wird wiedergegeben.


    Nun fehlt es uns eigentlich nurnoch an 2 Dialogen, dann sind wir fertig. Das ist einmal der Dialog für das vergessene Passwort und zum Ändern des Passwortes.
    if(dialogid == lostpw && response)
    {
    new answer[256];
    answer = dini_Get(path, "Antwort");


    if(!strcmp(answer,inputtext))
    {
    dini_Set(path, "PW", lostpws[random(15)]);
    new string[128], pw[256];
    pw = dini_Get(path, "PW");
    format(string, 128, "Dir wurde das Passwort \"%s\" zugeteilt. Ändere dies bitte nach dem Login mit /pwändern.", pw);
    SendClientMessage(playerid, COLOR_GREEN, string);
    }
    else SendClientMessage(playerid, COLOR_RED, "Deine Antwort war nicht korrekt.");
    return 1;
    }
    Hier läuft das ganze eigentlich auch recht einfach ab. Beim vergessenen Passwort wird zuerst die Antwort aus der Dini geladen und überprüft, ob sie mit der eingegebenen Antwort übereinstimmt. Ansonsten wird eine Nachricht ausgegeben. Wenn dem allerdings der Fall ist, dann wird aus dem Array lostpws den wir oben ja mit unseren Passwörtern definiert haben ein zufälliges von der Zahl 1-15 rausgepickt. Deshalb sollten wir uns die 15 merken. Wenn ihr 20 Passwörter eintragt, müsst ihr dies nämlich auf 20 ändern. Dieses Passwort wird in der Dini gespeichert und danach abgefragt. Wenn das Speichern nicht geklappt haben sollte, steht nun nochmal das alte Passwort da, das ja noch in der Dini eingetragen wäre.


    if(dialogid == pwchange && response)
    {
    new string[128];
    dini_Set(path, "PW", inputtext);
    format(string, 128, "Dein Passwort wurde erfolgreich auf \"%s\" geändert.", inputtext);
    SendClientMessage(playerid, COLOR_GREEN, string);
    return 1;
    }
    Nun, das ist wohl der leichteste Dialog. Zuerst wird das neue Passwort gespeichert, dann die Nachricht formatiert und dem Spieler gesendet.
    Achtung: Die Passwörter werden unverschlüsselt gespeichert und deshalb von Hackern oder Leuten mit Zugriff auf den Server einsehbar. Wenn ihr Sicherheit wollt, müsst ihr noch MD5-Crypt o. andere Verschlüsselungsverfahren einbauen.
    MD5: http://www.file-upload.net/download-3726477/md5.inc.html
    Whirlpool: http://forum.sa-mp.com/showthread.php?t=65290
    (Danke an Dudalus für die Links ;) )


    Das war es dann schon mit dem Tutorial. Ich hoffe es hat euch gefallen, geholfen und wenn ja- empfehlt es gerne weiter ;)


    Mit freundl. Grüßen
    Padarom

    Ich bin
    .. seit etwa 2007 in der Webentwicklung tätig, seit 2013 professionell
    .. Erfahrener Entwickler in PHP, Swift, Javascript, Typescript und Ruby. Zusätzlich habe ich Erfahrung in Python, Java, C#, C++, Prolog und einigen esoterischen Programmiersprachen
    .. Luftfahrtenthusiast und Segelflieger

    4 Mal editiert, zuletzt von Padarom () aus folgendem Grund: Links für Verschlüsselungen eingefügt

  • Oh natürlich, ich habe ausversehen beim /register Command den gleichen Dialog genutzt, also login. Ändere das in register1 und es funktioniert. Werde das im Tutorial auch gleich berichtigen.


    Mit freundlichen Grüßen
    Padarom

    Ich bin
    .. seit etwa 2007 in der Webentwicklung tätig, seit 2013 professionell
    .. Erfahrener Entwickler in PHP, Swift, Javascript, Typescript und Ruby. Zusätzlich habe ich Erfahrung in Python, Java, C#, C++, Prolog und einigen esoterischen Programmiersprachen
    .. Luftfahrtenthusiast und Segelflieger

  • Hi


    Ich empfehle dir wärmsten, das Passwort zu verschlüssen, da sowas meiner Meinung nach fahrlässig ist, da diverse Benutzer gleiche Passwörter verwenden:


    MD5: http://www.file-upload.net/download-3726477/md5.inc.html
    Whirlpool: http://forum.sa-mp.com/showthread.php?t=65290


    Gruss Simon

  • Eigentlich ein Recht gutes System. Nur was eventuell stören wird die meisten ist , das hier nicht mit
    Dialogen Gearbeitet wird. Sieht ansonsten aber sehr gut aus 8/10

  • Ablauf

    • Spieler registriert sich mit Passwort, geheimer Frage & geheimer Antwort.
    • Spieler vergisst sein Passwort und gibt ingame /passwortvergessen ein.
    • Spieler gibt die Antwort auf seine geheime Frage ein.
    • Wenn richtig wird ein neues Passwort (zufällig aus einer Liste vorgegebener Passwörter) erstellt und ihm zugewiesen.
    • Spieler kann sich mit diesem Passwort einloggen und danach mit /pwändern ein neues zuweisen.

    Wie gibt er InGame sein Passwort ein, wenn er es vergessen hat?
    Der kommt doch gar nicht rein, wenn er sein Passwort nicht weiß, oder? :huh:

  • Ich empfehle dir wärmsten, das Passwort zu verschlüssen, da sowas meiner Meinung nach fahrlässig ist, da diverse Benutzer gleiche Passwörter verwenden:

    Ich habe ja extra dazugeschrieben, dass die Passwörter aktuell unverschlüsselt übermittelt werden und man es deshalb erst noch mit MD5 oder sonstigem verschlüsseln soll, aber ich editiere die Links mal in den Startpost ;)

    Wie gibt er InGame sein Passwort ein, wenn er es vergessen hat?
    Der kommt doch gar nicht rein, wenn er sein Passwort nicht weiß, oder? :huh:

    Er kann doch connecten und dann /login eingeben. Wenn dann die Meldung kommt, dass das Passwort falsch ist, gibt er einfach /passwortvergessen ein, seine geheime Antwort und ihm wird ein neues PW zugeteilt - Ich glaube du hast da irgendwas missverstanden ;)


    edit Dome: Ich arbeite doch mit Dialogen? Alle Eingaben werden in Dialogen getätigt.


    Mit freundl. Grüßen
    Padarom

    Ich bin
    .. seit etwa 2007 in der Webentwicklung tätig, seit 2013 professionell
    .. Erfahrener Entwickler in PHP, Swift, Javascript, Typescript und Ruby. Zusätzlich habe ich Erfahrung in Python, Java, C#, C++, Prolog und einigen esoterischen Programmiersprachen
    .. Luftfahrtenthusiast und Segelflieger

  • do.de - Domain-Offensive - Domains für alle und zu super Preisen
  • C:\Users\Michel\Desktop\test\Neuer Ordner (2)\BibBoss\server\gamemodes\Neuer Ordner (3)\Test.pwn(77) : error 017: undefined symbol "SendClientMesssage"
    C:\Users\Michel\Desktop\test\Neuer Ordner (2)\BibBoss\server\gamemodes\Neuer Ordner (3)\Test.pwn(139) : warning 217: loose indentation
    C:\Users\Michel\Desktop\test\Neuer Ordner (2)\BibBoss\server\gamemodes\Neuer Ordner (3)\Test.pwn(140) : warning 217: loose indentation
    C:\Users\Michel\Desktop\test\Neuer Ordner (2)\BibBoss\server\gamemodes\Neuer Ordner (3)\Test.pwn(273) : error 001: expected token: ",", but found "]"
    C:\Users\Michel\Desktop\test\Neuer Ordner (2)\BibBoss\server\gamemodes\Neuer Ordner (3)\Test.pwn(273) : error 029: invalid expression, assumed zero
    C:\Users\Michel\Desktop\test\Neuer Ordner (2)\BibBoss\server\gamemodes\Neuer Ordner (3)\Test.pwn(273) : warning 215: expression has no effect
    C:\Users\Michel\Desktop\test\Neuer Ordner (2)\BibBoss\server\gamemodes\Neuer Ordner (3)\Test.pwn(295) : warning 217: loose indentation
    C:\Users\Michel\Desktop\test\Neuer Ordner (2)\BibBoss\server\gamemodes\Neuer Ordner (3)\Test.pwn(318) : error 002: only a single statement (or expression) can follow each "case"
    C:\Users\Michel\Desktop\test\Neuer Ordner (2)\BibBoss\server\gamemodes\Neuer Ordner (3)\Test.pwn(318 -- 319) : error 029: invalid expression, assumed zero
    C:\Users\Michel\Desktop\test\Neuer Ordner (2)\BibBoss\server\gamemodes\Neuer Ordner (3)\Test.pwn(334) : warning 225: unreachable code
    C:\Users\Michel\Desktop\test\Neuer Ordner (2)\BibBoss\server\gamemodes\Neuer Ordner (3)\Test.pwn(355) : warning 217: loose indentation
    Pawn compiler 3.2.3664 Copyright (c) 1997-2006, ITB CompuPhase



    5 Errors.
    habe alle drien so wie bei dir . Bitte helfe mir ein bitte