Server side scripting 1 Webtechnologie Lennart Herlaar
Inhoud PHP Meer PHP En nog meer PHP
Server side scripting 3 Webtechnologie Lennart Herlaar
Class based Object model herschreven voor PHP5, deels 5.3 Breuk met PHP4; incompatible legacy code Objects en classes Een object heeft functies en variabelen Methods en properties Methods en properties kunnen dynamisch aan objecten toegevoegd worden Een object is een instantiatie van een class Een class is een blauwdruk voor een object De classes vormen een hiërarchie Vergelijk dit met JavaScript...
Objecten class Cart { private $items; // Pas op! public function add_item ($artnr, $num) { $this->items[$artnr] += $num; } public function remove_item ($artnr, $num) { if ($this->items[$artnr] >= $num) { $this->items[$artnr] -= $num; return true; } else { return false; } $cart = new Cart; $cart->add_item("10", 1); $cart->add_item("42", 42); $another_cart = new Cart; $another_cart->add_item("0815", 3); Public, private, protected
Object dynamics Naast object dynamics ook class dynamics Lastiger dan prototype dynamics in JavaScript Probeer dit allemaal niet nodig te hebben... $cart1 = new Cart; $cart2 = new Cart; $cart2->add_item("a",10); $cart2->add_item("b",5); $cart1->val = "cart1"; echo ($cart1->val); // cart1 echo ($cart2->val); // Niets echo implode(";",$cart2->items); // 10;5 unset ($cart2->items); echo ($cart2->items); // Niets
Class inheritance Geen multiple inheritance Wel multiple interfaces class Named_Cart extends Cart { private $owner; function set_owner($name) { $this->owner = $name; } function get_owner() { return($this->owner); }
Constructors Magic Method met de naam __construct Constructor van super class moet expliciet aangeroepen worden Eveneens een destructor beschikbaar class Constructor_Cart extends Cart { function __construct($item = "10", $num = 1) { $parent::__construct(); $this->add_item ($item, $num); } $default_cart = new Constructor_Cart; $different_cart = new Constructor_Cart("20", 17);
Paamayim Nekudotayim Dubbele dubbele punt Scope resolution operator Static properties en methods Geen instantiatie nodig Overridden methods Methods van super classes Class constants class Foo { public static function myStaticFunc() { [...] } } Foo::myStaticFunc(); class OtherClass extends MyClass { public function myFunc() { [...] parent::myFunc(); }
Functies op objecten function print_vars($obj) { $vars = get_object_vars($obj); foreach ($vars as $prop => $val) { echo "$prop = $val\n"; } function print_methods($obj) { $methods = get_class_methods(get_class($obj)); foreach ($methods as $method) { echo "function $method()\n"; }
Zwak getypeerd, dynamisch Niet nodig variabelen of properties te declareren Type wordt "at runtime" bepaald, duck typing Automatische type conversion Functies zijn in de regel geen 1 st class citizens Functies en properties kunnen dynamisch aan objecten toegevoegd worden (maar…) Functies met mogelijk variabel aantal parameters Polymorfie Nesting van functiedefinities, closures (PHP5.3) Vergelijk dit met JavaScript...
Centraal architectuur diagram Webserver Web browser RDBMS Statische files Form, parameters HTML HTML+code SQL Parameters, code HTML File access Result set Interpreter of compiler
Superglobals PHP kent een aantal bijzondere variabelen Superglobals: automatisch beschikbaar in elke scope Arrays met (veelal) informatie over de buitenwereld $_SERVER: server en execution environment $_GET: key / value paren uit de GET query string $_POST: key / value paren uit de POST body Ook: $_FILES, $_COOKIE, $_SESSION, $_ENV $_REQUEST = $_GET + $_POST + $_COOKIE
Superglobals "; echo $_SERVER["SERVER_ADDR"]. " "; echo $_SERVER["SERVER_PORT"]. " "; echo $_SERVER["REQUEST_TIME"]. " "; echo $_SERVER["REQUEST_METHOD"]. " "; echo $_SERVER["REQUEST_URI"]. " "; echo $_SERVER["HTTPS"]. " "; echo $_SERVER["HTTP_USER_AGENT"]. " "; echo $_SERVER["REMOTE_ADDR"]. " "; echo $_SERVER["REMOTE_PORT"]. " "; ?>
Form processing First name: Last name: <?php echo $_GET["first"]; // Geen URL decoding nodig echo $_REQUEST["first"]; extract($_GET, EXTR_PREFIX_ALL, "imported") // Pas op! echo $imported_first; // Old-skool echo $HTTP_GET_VARS["first"]; // Met PHP directive register_globals = on echo $first; // Pas op! (Old skool; < PHP 5.4) ?>
Odds & ends Includen van PHP code include() en require() Local / remote, scoping Let op: HTML-context! Gebruik Aanpassen PHP settings Vele tientallen setting In de config file, maar soms ook "at runtime" ini_set('display_errors', 1), ini_get('post_max_size') Genereren van HTTP headers header(), maar pas op met whitespace... <?php // We serveren een PDF uit... header('Content-type: application/pdf'); //...en we noemen 'm doc.pdf header('Content-Disposition: attachment; filename="doc.pdf"'); [...] ?>
Heel veel functies in de core......en heel veel functies in extensions Compressie, cryptografie, cookies, beeldverwerking, , XML, file system, datum/tijd, sessions, URIs, FTP, databases, mathematische bewerkingen, TCP, sockets, HTTP, SOAP, JSON, LDAP, PDF, MIME,... We komen er nog een aantal van tegen State, sessions, databases, security, stateful web Belang van frameworks Odds & ends PEARPECL
phpinfo() PHP configuratie
State, sessions, databases 19 Webtechnologie Lennart Herlaar
Inhoud State Cookies en sessions Webdatabases Databases en PHP (Transactions)
State HTTP revisited HTTP is stateless HTTP kent page based requests In de regel geen continu draaiende applicatie Niet op de server, niet in de client Maar we willen wel persistency State moet ergens opgeslagen worden In de client, maar dan wel telkens meesturen In de server, maar dan wel een identificatieprobleem Verschillende opties
Hidden input fields State wordt "verborgen" in het formulier Hidden input fields, state opgeslagen in de client Bij submit worden deze waarden meegestuurd Onderdeel van de GET query string / POST body En opnieuw verwerkt door het server side script Problemen met hidden input fields Verwarrend: gebruik back button geeft verlies state Inefficiënt: alle state ping-pongt heen en weer Onveilig: de gebruiker kan eenvoudig bij de state Complex: scripten ping-pongen en input validation
Hidden input fields Product: Volvo Saab Fiat Audi Full name: Address: card number: card name:
card number: card name: Full name: Address: Hidden input fields shop.php?[...]step=buyerinfo&product=64625&price=8995 shop.php?[...]step=buyerinfo&product=64625&price=89
Hidden input fields <input type="hidden" name="checksum" value="7ce9e97f43808be0d23f0493c3e1345b"/> md5("step=buyerinfo&product=64625&price=8995") md5("step=buyerinfo&product=64625&price=8995MyLittleSecret") md5("step=buyerinfo&product=64625&price=89") 6ae e2c301b5eafa eece848a4c43a0b1144f863d770c66b <input type="hidden" name="checksum" value="6ae e2c301b5eafa463285"/> <input type="hidden" name="checksum" value="9eece848a4c43a0b1144f863d770c66b"/> md5("step=buyerinfo&product=64625&price=8995MyLittleSecretTimestamp") <input type="hidden" name="checksum" value="b ccd2548d24"/>
Feitelijk het opbouwen van state in de URL Bij gebruik van GET Generiek principe Alle state aan elke link toevoegen als query string Form action wordt het script met de state tot nu toe Maar pas op... Dan wel gebruik maken van POST Beter: met hidden input fields en GET of POST State opbouwen in URL <form name="input" action="shop.php?step=paymentinfo&[...]&product=64625" method="post"> Full name: Address: See special deals 't Heeft allemaal dezelfde problematiek!
State, sessions, databases 27 Webtechnologie Lennart Herlaar
Cookies State wordt als "brokje" data opgeslagen In de client Server geeft client opdracht cookie te zetten Client stuurt het cookie mee met elk request Indien cookie en request matchen Uitwisseling op basis van HTTP headers Server zet het cookie met Set-Cookie Cookies zijn key-value paren; associative array Set-Cookie: product=64625; Max-Age=3600 Cookie: product=64625
Cookies Cookies hebben aanvullende attributen Expires: wanneer het cookie verloopt (ook: Max-Age) Domain: voor welke domeinen het cookie geldig is Path:...en voor welke URLs binnen het domein Secure: of het via HTTPS verzonden moet worden HttpOnly: of het alleen bedoeld is voor HTTP requests Set-Cookie: userid=willie; Domain=shop.foo.com; Path=/accounts; Expires=Wed, 13-Jan :23:01 GMT; Secure; HttpOnly Set-Cookie: product=64625; Domain=.foo.com; Path=/; Expires=Wed, 05-Mar :30:01 GMT;
Cookies in PHP en JavaScript PHP ondersteunt op transparante wijze cookies Header output eerst, dus cookies ook eerst! Cookies zijn vanuit JavaScript bereikbaar Zowel lezen als schrijven is mogelijk Alleen indien matchend en geen HttpOnly document.cookie = 'koekje=hello;expires=Wed, 05 Mar :35:01 GMT'; var koekje = document.cookie; // let op: string met key-value paren! <?php $count = $_COOKIE["count"] + 1; setcookie("count", $count, time()+3600); echo $count; ?>
Cookies? Soorten cookies Persistent, Session, Supercookie, Trackingcookie,... Cookies lossen niet alle eerdere problemen op Inefficiënt, onveilig Daarnaast nieuwe specifieke problemen Cookies kunnen in de browser geweigerd worden Beperkingen m.b.t. aantal en omvang van cookies Cookies hebben een matige reputatie Wettelijke beperkingen aan het gebruik van cookies Cookies soms ten onrechte geweigerd
Web Storage Onderdeel van HTML5 Biedt persistent storage in de client Vergelijkbaar met cookies, maar... Meer opslagruimte (5MB per domein versus 50 x 4kB) Local storage per domein (≈ persistent cookie) Session storage per window (≈ session cookie) Associative array Uitsluitend een client side interface......en dus alleen te benaderen vanuit JavaScript var nrOfClicks = localStorage.getItem('clickcount'); nrOfClicks++; localStorage.setItem('clickcount', nrOfClicks); alert(nrOfClicks);
State in de gedaante van generieke session data De session data is opgeslagen op de server In een file of in een database Minimale identifier ping-pongt heen en weer Als cookie; desnoods in een query string Script uitgevoerd in context van de session data PHP ondersteunt op transparante wijze sessions PHPSESSID cookie bevat meestal de session identifier Bijvoorbeeld: vgdo5afs4o220s6d991cr1nhg042ax17 De session identifier is een voucher Sessions
Sessions in PHP <?php session_start(); //Pas op, voor eerste output if (!isset($_SESSION['count'])) { $_SESSION['count'] = 1; } else { $_SESSION['count']++; } [...] echo "Hello visitor, you have seen this page ". $_SESSION['count']. " times."; ?> <?php session_start(); session_regenerate_id(); ?> <?php session_start(); session_unset(); session_destroy(); ?>
Session bijzonderheden Uniciteit session identifier niet gegarandeerd Kans op conflict buitengewoon klein Diverse mogelijkheden om dit te verbeteren Defaults voor PHPSESSID cookie Expires: "0" (maar…), Path: "/" Fall-back naar session identifier in query string... Afhankelijk van settings en aanpasbaar Opslag van session data File system, in een bestand sess_PHPSESSID Eigen session handlers kunnen gedefinieerd worden
Zijn sessions veilig? Min of meer, maar het vergt wel aandacht... Use only cookies setting: voorkomt session hijacking t.g.v. shoulder surfing, bookmarking, referer URL,... Secure cookie attribuut: HTTPS vereist Goede keuze van Expires, Path, Domain, HttpOnly Aanvullende controles: IP-adres, etc. (maar...) Regelmatig wisselen van session identifier Betere generator voor de session identifier... Sessions werken in de praktijk goed (maar...)
State, sessions, databases 37 Webtechnologie Lennart Herlaar
Web SQL Web Storage soms met een client side database SQLite in Firefox: webappsstore.sqlite Is dit idee niet generieker te maken? Client side database Toegang met behulp van SQL, vanuit JavaScript Web SQL Onderdeel van HTML5 Inmiddels alweer deprecated... Gebrek aan "onafhankelijke implementaties" die geen SQLite gebruiken
Centraal architectuur diagram Webserver Interpreter of compiler RDBMS Files SQL Parameters, code File access Result set Web Browser + Applicatie HTML, CSS, JavaScript, JSON, … File Form, parameters, … HTML, JavaScript, JSON, … RDBMS SQL Result set