Gå til innhold

Garanti's hjelpetråd til PHP


Anbefalte innlegg

Må si meg enig med Lokaltog her. Å bruke exception i et slik tilfellet bryter faktisk med prinsippet bak exception i og med at det brukes for å håndtere hendelser som ikke følger normal flyt. At noen taster inn et ugyldig brukernavn og/eller epost-adresse ved registering av bruker er definitivt en del av normal flyt.

Lenke til kommentar
Videoannonse
Annonse
Jeg synes fremgangsmåten til erit01 ser utrolig tungvint ut, og jeg kan ikke forstå hvordan dette gir noen fordeler over fremgangsmåten jeg foreslo.

 

...

 

Er dette virkelig måten man bør kode på?

 

 

Må si meg enig med Lokaltog her. Å bruke exception i et slik tilfellet bryter faktisk med prinsippet bak exception i og med at det brukes for å håndtere hendelser som ikke følger normal flyt. At noen taster inn et ugyldig brukernavn og/eller epost-adresse ved registering av bruker er definitivt en del av normal flyt.

 

Til dere begge to: Helt enig. Den eneste grunnen til at mitt innlegg har noen verdi er at Garanti spurte om det gikk an å catche flere exceptions og gå videre. Det er naturligvis tungvindt og feil å gjøre det slik, og kanskje var det til og med galt å poste det, istedenfor å poste bare en forklaring på hvordan det egentlig bør gjøres (selv om jeg gjorde det óg... :) )

Endret av erit01
Lenke til kommentar

Lagde en metode til User-classen min:

 

	public function Create($Username, $Password1, $Password2){

	if(!$Password1 == $Password2){
		$Error->Add('The passwords submitted doesn\'t match');
	}
	if($this->Exist($Username)){
		$Error->Add('The username is taken');
	}

}

Problemet er jo at jeg har en Error-klasse som skal fange opp eventuelle feil, men den blir jo ikke oppfattet innenfor metoden. Hva skal jeg gjøre med det?

Lenke til kommentar

Jeg brukte type hinting for å spesifisere at jeg ønsket et "ErrorClass"-objekt som parameter til __construct(). Det er valgfritt, men jeg synes det er en god vane å ha, slik at man vet at objektet man mottar som parameter er av riktig type.

 

Jeg går ut fra at årsaken til at du ikke har tilgang til $error i metoden Create er at $error er definert i global scope. Variabler som defineres i global scope er ikke tilgjengelige i funksjoner og metoder med mindre du benytter nøkkelordet global, eller sender variablene som parametere til funksjonen. Når du har et objekt, så synes jeg det i denne situasjonen er greiest å lagre en referanse til $error i selve objektet, slik at flere funksjoner også kan benytte seg av $this->error for å lagre feilmeldinger.

 

Objekter sendes som referanser i PHP 5, som er en stor fordel. Dette betyr at når du kjører $this->error->add('message') i koden min ovenfor, så modifiserer du $error-objektet du sendte som parameter i __construct(). Det vil si at feilmeldingene blir tilgjengelige i $error-objektet senere i scriptet:

 

<?php

class User {
private $error;
public function __construct(ErrorClass $error, ...) {
$this->error = $error;
}
public function create() {
...
$this->error->add('Message');
...
}
}

$error = new ErrorClass();
$user = new User($error);

$user->create(...);

print_r($error->getMessages()); // skriver ut feilmeldingene som ble lagret i User::create()

?>

Koden ovenfor er eksempelkode, men jeg tror du skjønner tegninga når du ser det. Spør hvis du lurer på noe mer. :)

Endret av Lokaltog
Lenke til kommentar

Mange takk for svar! Fikk det til nå :)

 

Kan du/noen andre se på denne klassen? Vil den fungere optimalt? Kan jeg utnytte OOP ytterligere?

class ErrorBuffer {

private $Error = array();

	public function Add($ErrorMessage){
		$this->Error[] = $ErrorMessage;
	}

	public function ErrorFlush(){

		//Flushes the error buffer

		if($this->Error){

			$ErrorCollection .= '<ul class="error">'."\n";

			foreach($this->Error as $Case){
				$ErrorCollection .= "\t".'<li>'.$Case.'</li>'."\n";
			}

			$ErrorCollection .= '</ul>'."\n";

				return $ErrorCollection;
		}
	}

}

Lenke til kommentar
Kan du/noen andre se på denne klassen? Vil den fungere optimalt? Kan jeg utnytte OOP ytterligere?

Du kan utnytte OOP ytterligere helt til alt ligger i klasser. Ta C# som et eksempel; der har du ikke noe valg, der må en programmere OO og alt ligger i klasser til å begynne med. I PHP har man et valg, men det er bare for å beholde bakoverkompatibilitet til tidligere versjoner - du programmerer ikke helt OO før du programmer bare OO.

 

Det virker som om du prøver å programmere mer "riktig", noe som er utrolig (!) bra, men OOP er ikke det eneste man kan se på. Design patterns, seperasjon av backend/frontend og html/php er også noe du kan kikke på.

 

http://en.wikipedia.org/wiki/Design_patter...mputer_science)

http://www.ibm.com/developerworks/library/...hp-designptrns/

http://www.devarticles.com/c/a/PHP/Introdu...erns-Using-PHP/

http://www.google.no/search?hl=no&safe...3%B8k&meta=

http://www.google.no/search?hl=no&q=mv...3%B8k&meta=

Endret av Jonas
Lenke til kommentar
  • 2 uker senere...

Mulig dette blir litt mye kode, men la gå (delvis pseudokode):

 

Klassen Connection:

class Connection extends mysqli{

public $Link;
public function __construct(){

	$this->Link = new mysqli(...);
}

}

 

 

class User{

// Objektreferanser (?)
private $Error;
private $Connection;

public function __construct(ErrorBuffer $Error, Connection $Connection) {
	$this->Error = $Error;
	$this->Connection = $Connection;
}

// En drøss funksjoner

public function Create($Username, $Password1, $Password2){

	validate(input);

	if(Validering suksessfull){
		$this->Connection->Link->query('INSERT INTO `Users` (Username, Password, Salt) VALUES ("'.$Username.'", "'.$Password.'", "'.$Salt.'")');
	}
}
}

$this->Connection->Link->query() er jo ikke spesielt... sexy. Hvordan skal dette gjøres på en bedre måte?

Endret av Garanti
Lenke til kommentar

Synes opplegget ditt virker generelt litt tungvint. Jeg pleier å gjøre det veldig enkelt ved å ha en DB-klasse som har en statisk metode "query", slik at jeg hvor som helst kan kalle DB::query(...). Ser ikke umiddelbart hvordan du kan gjøre koden din så mye kortere uten å endre på strukturen. Det nærmeste jeg kommer er å lage en referanse til Link-variabelen à la $link = & $this->Connection->Link; $link->query(...), men det er ikke akkurat noen god måte å løse problemet på.

Lenke til kommentar

Ta en titt på __get().

 

<?php

class Connection {

	public $link;

	public function __construct () {

		$this -> link = new mysqli ( ... );

	}

	public function __get () {

		return $this -> link;

	}

}

class User {

	public function foo () {

		$this -> Connection -> query ( 'INSERT INTO `Users` (Username, Password, Salt) VALUES ("'.$Username.'", "'.$Password.'", "'.$Salt.'")' );

	}

}

?>

 

Edit: Jeg må nesten spørre .. Salter du hash og samtidig lagrer saltet i databasen? Da oppnår du ingen økt sikkehert. :p

 

Edit: Du vil sikkert også bli kvitt mye problemer dersom du bare holder deg til èn database-klasse, og ikke to, hvor den ene er knyttet gjennom den andre.

Endret av Jonas
Lenke til kommentar
Nei. Dersom man får tak i hashene har man jo samtidig saltet og da har man kommet like langt. Da er det null problem å lage en applikasjon som benytter seg av rainbowtables eller bruteforce.

Nei, det er sikrere å ha et salt per bruker enn per applikasjon. De må fremdeles vite kordan du bruker saltet og kordan du hasher uansett.

Man unngår fremdeles de store databasene over tekststrenger som matcher en hash uten salt.

Men for de paranoide, må man ha begge. :p

Endret av OISNOT
Lenke til kommentar
Nei, det er sikrere å ha et salt per bruker enn per applikasjon. De må fremdeles vite kordan du bruker saltet og kordan du hasher uansett.

Man unngår fremdeles de store databasene over tekststrenger som matcher en hash uten salt.

Men for de paranoide, må man ha begge. :p

Sikrere med forskjellige salt? Selvsagt, men ikke når du lagrer det sammen med passordet! Ærlig talt, det er da bedre å bruke et gjemt salt enn forskjellige salt som på den andre siden er kjent. Et salt kan ha uendlig antall kombinasjoner, men dersom man kjenner til saltet, hvor lang tid tror du det tar før man finner ut bruken av det?

Lenke til kommentar
Sikrere med forskjellige salt? Selvsagt, men ikke når du lagrer det sammen med passordet! Ærlig talt, det er da bedre å bruke et gjemt salt enn forskjellige salt som på den andre siden er kjent. Et salt kan ha uendlig antall kombinasjoner, men dersom man kjenner til saltet, hvor lang tid tror du det tar før man finner ut bruken av det?

Det er mulig men tar veldig lang tid. Uten å vite kordan du hasher må de ha database over alle mulige former. Og det er en veldig stor database med felt for hver sum og salt.

 

En kombinasjon er jo det eneste "sikre" om du vil.

hash('ripemd160', $application_salt . md5($user_passord . $user_salt))

Endret av OISNOT
Lenke til kommentar

Det tar ikke spesielt lang tid, nei. Det er veldig typisk å bare sette salt rett etter passordet, eller med en kombinasjon slik du viser. Man kan med litt fantasi sikkert lage ca. hundre forskjellige kombinasjoner, og det betyr at løsningen bare er hundre ganger sikrere dersom saltet er kjent. Med et ukjent salt må man ikke bare finne kombinasjon, men også selve saltet.

 

Edit: Herrejesus da, gutter - dette er da helt grunnleggende greier.. :(

 

Edit: Sammenlign problemstillingen med våpenloven for åpebevaring i Norge. Kanskje lettere med et tilfelle de fleste kan relatere seg til. Her er det slik at sluttstykket eller en eller annen nødvendig del skal taes vekk og lagres på et fullstendig separat sted. Dette er fordi at dersom noen finner våpenet, så er det urbukelig. Men tenk - i din egen retning - om man lagrer sluttstykket ved siden av selve våpenet, hvor lang tid tror du det tar før en tyv finner ut hvordan man fester sluttstykket og lader våpenet? Det kan være litt tricky, ettersom alle typer opereres forskjellig, men alle klarer det til slutt.

Endret av Jonas
Lenke til kommentar
Det tar ikke spesielt lang tid, nei. Det er veldig typisk å bare sette salt rett etter passordet, eller med en kombinasjon slik du viser. Man kan med litt fantasi sikkert lage ca. hundre forskjellige kombinasjoner, og det betyr at løsningen bare er hundre ganger sikrere dersom saltet er kjent. Med et ukjent salt må man ikke bare finne kombinasjon, men også selve saltet.

 

Edit: Herrejesus da, gutter - dette er da helt grunnleggende greier.. :(

 

Edit: Sammenlign problemstillingen med våpenloven for åpebevaring i Norge. Kanskje lettere med et tilfelle de fleste kan relatere seg til. Her er det slik at sluttstykket eller en eller annen nødvendig del skal taes vekk og lagres på et fullstendig separat sted. Dette er fordi at dersom noen finner våpenet, så er det urbukelig. Men tenk - i din egen retning - om man lagrer sluttstykket ved siden av selve våpenet, hvor lang tid tror du det tar før en tyv finner ut hvordan man fester sluttstykket og lader våpenet? Det kan være litt tricky, ettersom alle typer opereres forskjellig, men alle klarer det til slutt.

Vel, eg vil kun bruke både applikasjons og bruker salt. Har egentlig aldri tenkt på enten eller.

 

Din sammenligning er veldig forenklet. Å finne ut kordan man lader et våpen tar mindre tid enn å finne passordet. Det tar mye CPU tid, hvis du ikke har en veldig, veldig stor database for alle mulige måter å hashe en streng og salt (noe ingen har).

 

Hvis du skal beskytte et forum eller lignende så holder begge metodene hver for seg.

 

Skal du beskytte noe mer så bør du bruke et felles salt og et unikt salt per bruker.

Det er også en ide å bruke de samme listene crack programmer/databaser har over de vanligste passordene for å sperre dem (password, password_, password1, secret, etc).

Lenke til kommentar

Det du sier henger ikke på greip. Faktum er at et salt kan settes sammen med uendelig mange kombinasjoner og det er særdeles vanskelig å finne dersom det består av mer enn 20 tegn. En salt-metode derimot, kan gjettes på få kombinasjoner, fordi det er veldig typisk å bare sette sammen passord + salt, enten foran eller bak.

 

Det å lagre saltet sammen med passord har jeg aldri sett før nå, av den enkle grunn - det er ingen som gjør det! Jeg fikk nesten sjokk da jeg så dette. Det er rett og slett ingen god idé.

Lenke til kommentar
Gjest Slettet+6132

For alt vi vet kan personen ha lagret saltet sammen med passordet kun for at vi skal tro at saltet eksisterer, mens passordet i virkeligheten ikke er saltet i det heletatt. Om man da skulle ha gjetta salt-metoden ville man nok brukt litt lenger tid, men jeg tviler på at dette er tilfellet.

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...