2018-02-12, 19:23
  #1
Medlem
Vetenskapspojkens avatar
Hej!

Jag har ett HTML-formulär där användaren har möjlighet att skriva in ett användarnamn och ett lösenord, i syfte att "registrera sig". Jag vill bara klargöra att detta är en skoluppgift och inte ett seriöst projekt, då jag istället för MySQL kommer lagra användardata i en textfil.

I alla fall, användardatan skickas med POST-metoden från HTML-formuläret och sparas i variabler. Dessa ska sedan, som ovan nämnt, lagras i en textfil. Jag är medveten om att detta inte är ett säkert sätt att förvara användardata, så sådana kommentarer undanbedes.

Sagt och gjort, jag skapade en textfil (använder OS X) med file extention .rtf, och döpte den till "Database". Följande kod ska enligt vad jag förstått det spara användarnamnet i textfilen:

[PHP]
$username = $_POST["username"];

$database = fopen("Database.rtf", "w");
fwrite("$database", "$username");
fclose("$database");
[/PHP]

För att testa så har jag valt att bara lagra användarnamnet i textfilen först och främst, bara för att se om det fungerar.

I början fick jag ett felmeddelande med något i stil med "permission denied". Efter att ha googlat lite så inser jag att PHP (eller snarare XAMPP, vilket jag använder mig av), inte har rättigheter att skriva data på hårddisken, vilket föranleder detta felmeddelande.

Det jag gjorde för att lösa detta var att gå in i Applications > XAMPP > htdocs > "Database.rtf" > Get info > Sharing and Permissions > klickade på låset för att göra ändringar > ändra tillåtelse till "read and write" för "everyone" och sedan sparade jag ändringarna.

Nu verkar formuläret skickas utan allehanda felmeddelanden och allt är frid och fröjd. När jag sedan ska öppna "databasen", alltså textfilen som ligger i htdocs för att kontrollera att användarnamnet jag matade in finns där, så möts jag av en dialogruta där det står: "The document 'Database' could not be opened."

Jag misstänker att PHP har sabbat textfilen, och att den blivit korrupt eller något. Har någon av er haft något liknande problem, och om ja, hur löste ni detta?
Citera
2018-02-12, 20:20
  #2
Medlem
Inte hundra på OSX, men en misstanke är ju att RTF-formatet inte stödjer rå ASCII, vilket väl är vad du skriver till filen. Testa att byta namn till .txt eller bara öppna filen i en annan editor. Enklast kanske att använda cat i en terminal.
Citera
2018-02-12, 20:43
  #3
Medlem
Vetenskapspojkens avatar
Citat:
Ursprungligen postat av luxnest
Inte hundra på OSX, men en misstanke är ju att RTF-formatet inte stödjer rå ASCII, vilket väl är vad du skriver till filen. Testa att byta namn till .txt eller bara öppna filen i en annan editor. Enklast kanske att använda cat i en terminal.

Okej, tack för ditt svar! Är inte .txt bara Windows motsvarighet till .rtf i OS X? Jag använder för övrigt "Text Editor" som är som Notepad i Windows, men jag ska testa att ändra file extention till .txt!
Citera
2018-02-12, 22:39
  #4
Medlem
Vetenskapspojkens avatar
Citat:
Ursprungligen postat av luxnest
Inte hundra på OSX, men en misstanke är ju att RTF-formatet inte stödjer rå ASCII, vilket väl är vad du skriver till filen. Testa att byta namn till .txt eller bara öppna filen i en annan editor. Enklast kanske att använda cat i en terminal.

Nu gick det lite för lång tid för att jag skulle kunna redigera mitt tidigare inlägg och lägga till en edit, så jag får helt enkelt skriva ett nytt inlägg.

I alla fall, tack så mycket! Det fungerade klockrent. Jag trodde att filformatet .txt var Windows only, som den efterblivna Mac-användare jag ju är

Nu har jag alltså lyckats skapa ett formulär där användaren kan mata in önskvärt användarnamn och lösenord. Dessa skickas med metoden post, och med lite kodtrolleri så hamnar dessa i min "databas", alltså en textfil.

Vad lösenordet beträffar så kan man ju trycka in det på samma sätt som med användarnamnet, men för att åtminstone implementera någon typ av säkerhet, så har jag använt password_hash(). Min lärare sa dessutom att hashen ska vara saltad, men vad fan menas med det? Aja, jag antar att jag får googla det på egen hand, men nu till en övrig fråga, då du verkar kunnig:

Nu har användarnamnet och lösenordet (i form av en hash) skrivits till textfilen. När jag öppnar textfilen så ser det ut ungefär såhär:

Citat:
Vetenskapspojken9384yqno98wylnfohlsaiflnv

Kan man på något sätt snygga till det lite? Så att det förslagsvis ser ut som något i stil med detta:

Citat:
Username: Vetenskapspojken
Password: 9384yqno98wylnfohlsaiflnv

Här är min kod för övrigt:

[PHP]

if(isset($_POST["register"])) {

$username = $_POST["username"];
$password = $_POST["password"];

$database = fopen("Database.txt", "w");

fwrite($database, $username);
fwrite($database, password_hash($password, PASSWORD_DEFAULT);
fclose($database);

}
[/PHP]
Citera
2018-02-12, 22:59
  #5
Medlem
Skriver på telefonen så det riskerar att bli knas, men testa följande:

fwrite($database, "Username: " . $username . PHP_EOL . "Password: " . osv...)

Punkterna klistrar ihop strängen till vänster och höger, och PHP_EOL är en strängkonstant som motsvarar radbrytning på din maskin. Du kan läsa mer om strängar på http://php.net/manual/en/language.operators.string.php .

Vad gäller att salta lösenord så finns det massor online; kort sagt så handlar det om att göra det svårare att slå upp lösenordshashen i diverse "ordböcker" som finns för detta syfte. Du sparar saltet, en textsträng, och hashar lösenordet sammanslaget med saltet. Saltet kan sparas i klartext.

Det som det handlar om är att om saltet till exempel är "aaaa", och lösenordet är "password123", så är det mindre sannolikt att någon har hashen för "aaaapassword123" i ordboken än hashen för bara "password123". Dock så är exemplet inte så bra, och saltet ska alltså slumpas fram, men du måste spara det så att du kan klistra ihop det med det angivna lösenordet när du sen ska jämföra hasharna. Kolla kanske på nätet för jag insåg att det inte går att göra sig förstådd med telefonens tangentbord
Citera
2018-02-12, 23:00
  #6
Medlem
Protons avatar
Citat:
Ursprungligen postat av Vetenskapspojken
Nu gick det lite för lång tid för att jag skulle kunna redigera mitt tidigare inlägg och lägga till en edit, så jag får helt enkelt skriva ett nytt inlägg.

I alla fall, tack så mycket! Det fungerade klockrent. Jag trodde att filformatet .txt var Windows only, som den efterblivna Mac-användare jag ju är

Nu har jag alltså lyckats skapa ett formulär där användaren kan mata in önskvärt användarnamn och lösenord. Dessa skickas med metoden post, och med lite kodtrolleri så hamnar dessa i min "databas", alltså en textfil.

Vad lösenordet beträffar så kan man ju trycka in det på samma sätt som med användarnamnet, men för att åtminstone implementera någon typ av säkerhet, så har jag använt password_hash(). Min lärare sa dessutom att hashen ska vara saltad, men vad fan menas med det? Aja, jag antar att jag får googla det på egen hand, men nu till en övrig fråga, då du verkar kunnig:

Nu har användarnamnet och lösenordet (i form av en hash) skrivits till textfilen. När jag öppnar textfilen så ser det ut ungefär såhär:



Kan man på något sätt snygga till det lite? Så att det förslagsvis ser ut som något i stil med detta:



Här är min kod för övrigt:

[PHP]

if(isset($_POST["register"])) {

$username = $_POST["username"];
$password = $_POST["password"];

$database = fopen("Database.txt", "w");

fwrite($database, $username);
fwrite($database, password_hash($password, PASSWORD_DEFAULT);
fclose($database);

}
[/PHP]
Ska du använda datat till något vettigt, dvs att från din fil läsa in datat och sedan jämföra det kmed något, i sådana fall blir din lösning skitjobbig eftesom du manuellt blir tvungen att parsa filen för att få reda på vad username och password är.

Ett bättre alternativ i sammanhanget är ju då isf att använda serialize-funktionen som är inbyggd i php, då kan du serialisera en associativ array till exempel och sen läsa in den från fill tillbaka till en associativ array.

[PHP]
if(isset($_POST["register"])) {

$username = $_POST["username"];
$password = $_POST["password"];

$userData = Array("username" => $username, "password" => password_hash($password, PASSWORD_DEFAULT));

$database = fopen("Database.txt", "w");

fwrite($database, serialize($userData));
fclose($database);

[/PHP]

Så nånting.

För att sedan läsa upp datat från fil igen kan du kika på funktionen unserialize, men det får bli nästa övning för dig.

Vill du däremot fortfarande av nån anledning få det uppställt på olika rader får du väl tåta ihop en sträng manuellt med radbryt etc och sen spara det i filen.

[PHP]

if(isset($_POST["register"])) {

$username = $_POST["username"];
$password = $_POST["password"];

$database = fopen("Database.txt", "w");

$pw = password_hash($password, PASSWORD_DEFAULT);

$strToSave = "username : " . $username."\n";
$strToSave .= "password : " .$pw;

fwrite($database, $strToSave);
fclose($database);

}
[/PHP]
__________________
Senast redigerad av Proton 2018-02-12 kl. 23:04.
Citera
2018-02-12, 23:50
  #7
Medlem
Vetenskapspojkens avatar
Citat:
Ursprungligen postat av luxnest
Skriver på telefonen så det riskerar att bli knas, men testa följande:

fwrite($database, "Username: " . $username . PHP_EOL . "Password: " . osv...)

Punkterna klistrar ihop strängen till vänster och höger, och PHP_EOL är en strängkonstant som motsvarar radbrytning på din maskin. Du kan läsa mer om strängar på http://php.net/manual/en/language.operators.string.php .

Vad gäller att salta lösenord så finns det massor online; kort sagt så handlar det om att göra det svårare att slå upp lösenordshashen i diverse "ordböcker" som finns för detta syfte. Du sparar saltet, en textsträng, och hashar lösenordet sammanslaget med saltet. Saltet kan sparas i klartext.

Det som det handlar om är att om saltet till exempel är "aaaa", och lösenordet är "password123", så är det mindre sannolikt att någon har hashen för "aaaapassword123" i ordboken än hashen för bara "password123". Dock så är exemplet inte så bra, och saltet ska alltså slumpas fram, men du måste spara det så att du kan klistra ihop det med det angivna lösenordet när du sen ska jämföra hasharna. Kolla kanske på nätet för jag insåg att det inte går att göra sig förstådd med telefonens tangentbord

Nice, riktigt fint svar du knåpade ihop telefonens tangentbord till trots!

Just det, vanlig strängkonkatenering helt enkel. Jag vet hur man använder punkterna hehe, men ibland får man hjärnsläpp. Tänkte dock att det kanske var annorlunda när man skrev till en fil eller så, för det har jag aldrig gjort förut. Det är ju samma sak som att köra en echo med någon paragraf + någon variabel och sedan konkatenerar man ett utropstecken, typ. Den enda skillnaden är att PHP_EOL fungerar som en <br />, vilket är en ny lärdom för mig!

Okej, jag får nog söka lite efter hur man saltar sin hash, och ska inte störa dig mer. Eventuellt att jag postar i tråden om jag får något problem, men ska försöka lösa det på egen hand först!
Citera
2018-02-12, 23:58
  #8
Medlem
Vetenskapspojkens avatar
Citat:
Ursprungligen postat av Proton
Ska du använda datat till något vettigt, dvs att från din fil läsa in datat och sedan jämföra det kmed något, i sådana fall blir din lösning skitjobbig eftesom du manuellt blir tvungen att parsa filen för att få reda på vad username och password är.

Ett bättre alternativ i sammanhanget är ju då isf att använda serialize-funktionen som är inbyggd i php, då kan du serialisera en associativ array till exempel och sen läsa in den från fill tillbaka till en associativ array.

[PHP]
if(isset($_POST["register"])) {

$username = $_POST["username"];
$password = $_POST["password"];

$userData = Array("username" => $username, "password" => password_hash($password, PASSWORD_DEFAULT));

$database = fopen("Database.txt", "w");

fwrite($database, serialize($userData));
fclose($database);

[/PHP]

Så nånting.

För att sedan läsa upp datat från fil igen kan du kika på funktionen unserialize, men det får bli nästa övning för dig.

Vill du däremot fortfarande av nån anledning få det uppställt på olika rader får du väl tåta ihop en sträng manuellt med radbryt etc och sen spara det i filen.

[PHP]

if(isset($_POST["register"])) {

$username = $_POST["username"];
$password = $_POST["password"];

$database = fopen("Database.txt", "w");

$pw = password_hash($password, PASSWORD_DEFAULT);

$strToSave = "username : " . $username."\n";
$strToSave .= "password : " .$pw;

fwrite($database, $strToSave);
fclose($database);

}
[/PHP]

Ja, datan ska inte bara matas in i databasen och ligga där och damma, utan finnas där då man även har möjlighet att logga in och, förutsatt att kombinationen av användarnamn och lösenord matchar, komma till en annan sida.

Jag har nu testat mitt program lite, och märker att om jag registrerar två användare efter varandra, så finns bara den senast registrerade. De "samlas inte på hög" så att säga.

Egentligen är inte detta något krav för uppgiften, det räcker med att bara skapa ett konto och att inloggningen fungerar korrekt, men jag skulle gärna vilja att samtliga registrerade användare finns i databasen. Detta bör väl inte vara så svårt att ordna? Är det så serialize-funktionen fungerar?

I alla fall, jag ska testa att använda serialize-funktionen först istället för fopen() och fwrite(), och sedan återkommer jag med ytterligare funderingar.

Tack!
Citera
2018-02-13, 00:08
  #9
Medlem
Citat:
Ursprungligen postat av Vetenskapspojken
Jag har nu testat mitt program lite, och märker att om jag registrerar två användare efter varandra, så finns bara den senast registrerade. De "samlas inte på hög" så att säga.

Kolla http://php.net/manual/en/function.fopen.php speciellt under "mode" (där du nu har "w").
Citera
2018-02-13, 01:30
  #10
Medlem
Vetenskapspojkens avatar
Citat:
Ursprungligen postat av luxnest
Kolla http://php.net/manual/en/function.fopen.php speciellt under "mode" (där du nu har "w").

Okej, följaktligen borde jag använda "w+" som mode, som då tillåter både read/write. Nu ändrade dock mitt projekt lite riktning då jag lagrar datan i en array istället (en så kallad associative array), med hjälp av serialize().
Citera
2018-02-13, 01:40
  #11
Medlem
Vetenskapspojkens avatar
Citat:
Ursprungligen postat av Proton
Ska du använda datat till något vettigt, dvs att från din fil läsa in datat och sedan jämföra det kmed något, i sådana fall blir din lösning skitjobbig eftesom du manuellt blir tvungen att parsa filen för att få reda på vad username och password är.

Ett bättre alternativ i sammanhanget är ju då isf att använda serialize-funktionen som är inbyggd i php, då kan du serialisera en associativ array till exempel och sen läsa in den från fill tillbaka till en associativ array.

Jag testade detta! Det fungerade visserligen, men jag får lite konstig "output" i textfilen dit datan skrivs.

Citat:
a:2:{s:8:"username";s:16:"Vetenskapspojken";s:8:"p assword";s:60:"$2y$10$A1gTs62aU9JFl.EHvr9.u.gPmxo7 .qbRWCdPqF3IXzWL.yZ56IY0K";}

Ska det se ut såhär? Kan man på något sätt bli av med dessa "s:8" och "s:60"? Vad betyder dessa?

Och vad är skillnaden på att använda serialize() och sedan unserialize() jämfört med att köra fopen($database, "w+"), alltså tillåta både read/write genom att ändra mode från "w" till "w+"?

Sorry om det är virrigt och/eller efterblivet, som du säkert märker så är jag lite grön på detta.
Citera
2018-02-13, 07:17
  #12
Medlem
Protons avatar
Citat:
Ursprungligen postat av Vetenskapspojken
Jag testade detta! Det fungerade visserligen, men jag får lite konstig "output" i textfilen dit datan skrivs.



Ska det se ut såhär? Kan man på något sätt bli av med dessa "s:8" och "s:60"? Vad betyder dessa?

Och vad är skillnaden på att använda serialize() och sedan unserialize() jämfört med att köra fopen($database, "w+"), alltså tillåta både read/write genom att ändra mode från "w" till "w+"?

Sorry om det är virrigt och/eller efterblivet, som du säkert märker så är jag lite grön på detta.
Det är inget konstigt med denna output, det är resultatet av att ha serialiserat din array, då ser den ut sådär.

Du ska inte röra den det där datat, gör du det kommer du inte kunna köra unserialize på det och få tillbaka det som en associativ array, s8 och s50 anger ett offset i strängen, i detta fall hur många tecken som ingår i ditt username respektive password.


Serialize är således inte direkt avsett att vara human readable, men fördelen är att när du kör en unserialize på det kommer det tillbaka som en associativ array som du kan använda direkt utan att behöva själv lista ut var ditt password och usernamn börjar och slutar.

Serialize och fopen har inte mycket med varandra att göra btw, fopen öppnar en fil, serialize serialiserar ett objekt, variabel eller array så du kan spara den på fil i serialiserad form och sedan läsa tillbaka den och använda den som om inget hänt med unserialize. Hur hade du annars tänkt att spara exempelvis en array på disk? Visst, det går ju såklart att hitta på sitt eget sätt att spara det, men varför uppfinna hjulet igen, speciellt eftersom det riskerar att bli fyrkantigt, när det finns inbygga konstruktioner för att göra samma sak, fast mycket bättre?

Läs php-manualen nu om serialize och fopen så ska du se att det klarnar.
__________________
Senast redigerad av Proton 2018-02-13 kl. 07:22.
Citera
  • 1
  • 2

Skapa ett konto eller logga in för att kommentera

Du måste vara medlem för att kunna kommentera

Skapa ett konto

Det är enkelt att registrera ett nytt konto

Bli medlem

Logga in

Har du redan ett konto? Logga in här

Logga in