Slides 10

advertisement
State, sessions, databases
Lennart
Herlaar
Webtechnologie
1
Inhoud
• State
• Cookies en sessions
• Webdatabases
• Databases en PHP
• (Transactions)
State, sessions, databases
Cookies en sessions
Lennart
Herlaar
Webtechnologie
3
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
Set-Cookie: product=64625; Max-Age=3600
Cookie: product=64625
• Cookies zijn key-value paren; associative array
Cookies in PHP en JavaScript
• PHP ondersteunt op transparante wijze cookies
<?php
$count = $_COOKIE["count"] + 1;
setcookie("count", $count, time()+3600);
echo $count;
?>
• 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=Fri, 09 Mar 2016 14:35:01 GMT';
var koekje = document.cookie; // let op: string met key-value paren!
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
var nrOfClicks = localStorage.getItem('clickcount');
• Biedt
persistent storage in de client
nrOfClicks++;
localStorage.setItem('clickcount', nrOfClicks);
alert(nrOfClicks);
• 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
Sessions
• 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 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
<?php
session_start();
session_start();
unset($_SESSION['count']);
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
Webdatabases
Lennart
Herlaar
Webtechnologie
12
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
RDBMS
HTML, CSS,
JavaScript, JSON, …
File
HTML, JavaScript,
JSON, …
Files
Interpreter
of compiler
Result set
Webserver
SQL
Parameters, code
File access
Result set
SQL
Web
Browser
+
Applicatie
Form, parameters,
…
RDBMS
Webdatabases?
• Wenselijke eigenschappen van RDBMSen
•
•
•
•
•
Stabiele structuur van data
Grote hoeveelheden data
Goede performance
Meerdere gebruikers tegelijkertijd (transactions)
Betrouwbaarheid en integriteit van data
• Uitbreiding van webapplicatie met een RDBMS
voor storage ligt voor de hand
• B.v. producten en bestellingen binnen een webshop
• Databases op het web is een betere benaming
Computing models revisited
• Three-tier C/S model past goed bij het web
1. Webbrowser functioneert als thin client
2. Webserver functioneert als application server
3. Database server voor database en transaction logic
• Eventueel loskoppeling webserver en applicatie
• Diverse technieken voor integratie
•
•
•
•
Leverancier-specifieke technieken, eigen webservers
Gebruikelijke ondersteuning in programmeertalen
Java: Java DataBase Connectivity (JDBC)
Server side scripting talen
Server side scripting & RDBMSen
• Server side scripting talen hebben in de regel
faciliteiten voor interactie met een RDBMS
•
•
•
•
Vaak in de vorm van extensions, modules, libraries
Perl DBI-modules
PHP extensions
Maar ook: RDBMS support in de core
• Leverancier-specifiek versus abstractielagen
• Vaak een platform-specifieke driver nodig
• Interactie vaak op basis van SQL en result set
• Client/server request en response
Database smaken
• Er zijn vele tientallen RDBMSen beschikbaar
• Oracle, MS SQL Server, MySQL, PostgreSQL, SQLite
• MS Access, Excel (!)
• "Wat is het beste RDBMS?"
• Holy Wars! Vergelijk: taal, OS, telefoon, ...
• Betere vraag: "gegeven mijn specifieke situatie?"
• "Use the tool that does the job best"
• Requirements, license, features, stabiliteit, eenvoud,
schaalbaarheid, performance, kennis, support, kosten
Databases op het web
• HTTP revisited
• HTTP is stateless
• HTTP kent page based requests
• Gevolgen voor database interactie
• 1 tot vele tientallen queries per pagina
• Queries vaak relatief eenvoudig; binnen een context
• Transactions over meerdere requests problematisch
• Snelheid versus features?
• Snelheid versus betrouwbaarheid en integriteit?
De populairste opties
• MySQL en SQLite zijn populaire keuzes
• Gratis (maar...), snel, relatief eenvoudig
• Inmiddels ook een behoorlijke featureset
• ACID-compliant database platformen
• MySQL is een client/server RDBMS
• SQLite is een file database
• Geen eigen server proces
• Access mechanisme (library) gelinkt in de client(s)
• "Concurrent" writes op basis van file locking!
SQLite overwegingen
•
•
•
•
SQLite
SQLite
SQLite
SQLite
files zijn portable
werkt zonder users / passwords
is "weakly typed"
wordt vaak client side gebruikt
• Browsers, mobile devices
• SQLite is niet zo heel serieus...
• ...als server side database platform voor grote sites
• ...maar voldoet prima bij een practicumopdracht
• Zero-install footprint!
• De trend is overigens weer naar client side state!
State, sessions, databases
Databases en PHP
Lennart
Herlaar
Webtechnologie
22
Databases en PHP
• Database ondersteuning in PHP is uitgebreid
• Specifieke extensions voor > 20 platformen
• Daarnaast abstraction layers
• Portability is een aandachtspunt
•
•
•
•
Platform-specifieke functienamen en parameters
mysqli_query, pg_query, ...
Maar wel platform-specifieke features benaderbaar
Eigen database abstraction library schrijven?
• MySQL en SQLite support native in PHP aanwezig
• Afhankelijk van versie en compilatie-opties
Databases en PHP
<?php
if (!($cnx = @pg_connect("host=somehost dbname=somedatabase
user=someuser password=somepassword"))) {
showerror();
}
if (!($result = pg_query($cnx, "SELECT * FROM products"))) {
showerror();
}
echo "<ul>\n";
while ($row = pg_fetch_array($result)) {
echo "<li>" . $row["description"] . " : " . $row["price"] .
"</li>\n";
}
echo "</ul>\n";
pg_close($cnx);
?>
Database abstraction library?
function db_connect ($type, $host, $database, $user, $password) {
if ($type == 'pgsql') {
if (!($cnx = @pg_connect("host=$host dbname=$database
user=$user password=$password"))) {
showerror();
}
}
elseif ($type == 'mysql') {
if (!($cnx = @mysql_connect($host, $user, $password))) {
showerror();
}
mysql_select_db($database, $cnx) or showerror();
}
return $cnx;
}
PHP database abstraction layers
• Diverse database abstraction layers beschikbaar
• Deels in de core, deels in PEAR/PECL, deels extern
• PDO, dbx, ODBC, ...
• PHP Data Objects (PDO)
• Standaard in PHP aanwezig
• Data-access abstraction, niet database abstraction
• Dezelfde functies voor queries en result sets
• Geen herschrijving van SQL statements
• Geen bijzondere functionaliteit (wel via PDO drivers)
PDO
<?php
try {
$dbh = new PDO('sqlite:mydbfile.sqlite');
$sth = $dbh->query("SELECT * FROM products");
echo "<ul>\n";
foreach ($sth as $row) {
echo "<li>" . $row["description"] . " : " . $row["price"] .
"</li>\n";
}
echo "</ul>\n";
$dbh = NULL;
}
catch(PDOException $e) {
echo "Exception: " . $e->getMessage();
}
?>
PDO prepare & execute
<?php
<?php
$sth = $dbh->prepare('SELECT name, colour, calories
$sth = $dbh->prepare('SELECT
name, colour, calories
FROM fruit
FROM
WHEREfruit
calories < :calories
WHERE
calories
< :calories
AND colour
= :colour');
<?php
AND colour = :colour');
$calories
= 150;
$sth
=
$dbh->prepare('SELECT
name,
colour,
calories
$sth->bindParam(':calories',
$calories,
PDO::PARAM_INT);
$colour = 'red';
FROM fruit
$sth->bindParam(':colour',
$colour,
PDO::PARAM_STR, 12);
$sth->execute(array(':calories'
=> $calories,
WHERE
calories
< ? AND colour = ?');
$calories = 150;
':colour'
=>
$colour));
$sth->bindParam(1,
$calories, PDO::PARAM_INT);
$colour
=
'red';
[...]
$sth->bindParam(2,
$colour, PDO::PARAM_STR, 12);
$sth->execute();
?>
<?php
$calories
= 150;
[...]
$sth
= $dbh->prepare('SELECT
name, colour, calories
$colour
= 'red';
FROM fruit
$sth->execute();
$calories = 90;
WHERE calories < ? AND colour = ?');
[...]
$colour = 'green';
= 150;
?>$calories
$sth->execute();
$colour = 'red';
[...]
$sth->execute(array($calories, $colour));
?>[...]
?>
PDO observaties
• Class based
• Exception handling
• try – catch; informatief, maar niet te informatief
• PDO versus PDOStatement
• Database handle versus query en result set
• Query versus prepare & execute: templates!
• Efficiëntie en security; voorkomen SQL injection
• Let op data type
• Ook data manipulatie en data definitie
• INSERT, DELETE, CREATE TABLE, DROP TABLE
Frameworks en databases
• Sommige PHP frameworks werken met ORM
• Object Relational Mapping; vaak onderdeel MVC
• Virtuele object database; persistent objects
• Conversie van objecten naar RDBMS records
• Een tabel is een class, een record is een object
• OR impedance mismatch; lastig
That probleem
hurts!
• Soms alleen: SQL samenstellen; result in arrays
• ORM abstractie bovenop een PDO abstractie
waar een ODBC abstractie gebruikt wordt om
een SQLite abstractie van een file te benaderen?
Session data en databases
• Is session data ook data? Ja!
• Producten, bestellingen en winkelmandjes
• PHP gebruikt files voor opslag session data
• Een database is vaak handiger
• Grote verzameling sessions verstopt het file system
• Niet erg toegankelijk voor externe toepassingen
• Schaalt moeizaam: multi-server omgeving
• Twee mogelijkheden
• Expliciet afhandelen van sessions
• Herdefiniëren van default session handlers
State tables
• Session data komt terecht in state tables
• Basis: session identifier, key, value
• Maar ook maatwerk mogelijk; inpassen in database
• Reguliere database tabellen met enkele extra velden
• Functies nodig voor create, read, update, delete
• En een garbage collection mechanisme
• Session data is immers veelal tijdelijk van aard
State tables
session_start();
$dbh = new PDO('sqlite:statedb.sqlite');
$sth = $dbh->prepare("SELECT count(*) AS count FROM visitors
WHERE sessionid = ?");
$sth->bindValue(1, session_id(), PDO::PARAM_STR);
$sth->execute();
$row = $sth->fetch();
$count = $row['count'];
if ($count == 0) {
$sth = $dbh->prepare("INSERT INTO visitors (sessionid, lastvisit)
VALUES (:sessionid, :time)");
}
else {
$sth = $dbh->prepare("UPDATE visitors SET lastvisit = :time
WHERE sessionid = :sessionid");
}
$sth->bindValue(':sessionid', session_id(), PDO::PARAM_STR);
$sth->bindValue(':time', time(), PDO::PARAM_INT);
$sth->execute();
State tables
class MySessionHandler extends SessionHandler {
• Herdefiniëren
van default session handlers
•
public function read($sessionid) {
session_set_save_handler("open",
"close",
"read",
global $sess_save_path;
session.save_handler
op "user"
in plaats
van
"write", "destroy", "gc");
"file"
$sess_file = "$sess_save_path/sess_$sessionid";
• Definiëren
van functies voor afhandelen sessions
session_set_save_handler($handler);
return (string) @file_get_contents($sess_file);
} // Vervang dit door een state table query
• Toegang state tables onderbrengen in deze functies
[...]
• Sessions
kunnen normaal gebruikt worden
}
$handler = new MySessionHandler();
• session_start,
$_SESSION
session_set_save_handler($handler);
session_start();
• Transparant,
maar wel lastiger om op te zetten
Download