Unu situ web chene cookie? Eja, faghet
In s'incumentzu de sa carriera mia de programmadore web mi praghiat a fàghere a manera chi is sitos mios funtzionarent bene finas chene JavaScript e chene cookie. Acontessiat fatu-fatu difatis chi unos cantu impitadores nde ddos istudarent pro resones de seguresa. A pustis de s'arribu de sa lege de is cookie (o testimòngios), su pensamentu miu est torradu a bàlere. S'informu obligatòriu in totu is sitos chi bisitamus est de su totu infadosu e pro chie non nde ischit de chistiones legales ddoe at semper s'arriscu de fàghere is cosas non cunforma a is règulas. Balet sa pena, duncas, de si domandare si est pretzisu de a beru a installare custos cookie.
Incumentzamus narende chi, a foras de is trastos de sighidura comente Google Analytics, s'impreu primàriu de is cookie est su de mantènnere una sessione (is chi ddi narant "cookie tècnicos"), mentres su de ammentare is preferèntzias de s'impitadore oramai si faghet giai semper cun sa sessione etotu e s'archiviatzione locale pro mèdiu de JavaScript. Si chistionat giai de acabbare cun s'impreu de is cookie in pagos annos e esistint tècnicas de sighidura chi non ddos impreant, ma inoghe bògio ispricare comente si podet mantènnere una sessione in seguresa chene impreare custu trastu.
Aplicatziones de una pàgina
Is aplicatziones de una pàgina sunt cussos sitos web in ue su navigadore càrrigat in s'incumentzu una pàgina isceti e su cuntènnidu suo ddu manìgiat de su totu JavaScript. Servìtzios chi impreamus ònnia die sunt fatos in custa manera. Facebook est s'esempru prus craru, ma sunt de aici fintzas su motore de chirca de Google e àteros meda. Tenimus trastos vàrios a disponimentu pro creare sitos de una pàgina, comente is framework AngularJS e React, ma faghet a s'arrangiare fintzas cun sa paja Laravel + Livewire o àteru.
Su bonu de custa tècnica est chi, comente non tocat a carrigare prus pàginas, non tocat a si preocupare de recuperare sa sessione de traballu. Faghet a traballare a s'aplicatzione comente si esseret unu servìtziu web (web service), separende de su totu is lados server e client. Unu servìtziu web bonu est chene istadu, comente previdit su protocollu HTTP, e depet averiguare is credentziales de s'impitadore pro ònnia pedida. Non ddoe at a èssere duncas nissuna sessione, ma isceti resursas chi s'impitadore at a manigiare impreende pedidas vàrias (de bìdere su cuntzetu de serbidore RESTful).
Fitianamente, amus a tènnere unu serbidore de autenticatzione chi at a creare unu token. Cust'ùrtimu at a èssere sarvadu in locale (in una variàbile JavaScript o in s'archiviatzione de su navigadore) e agiuntu a s'intestatzione (header) de ònnia pedida a su serbidore web, chi dd'at a impreare pro identificare a s'impitadore.
Non m'apo a lereddiare nen cun is cuntzetos de autenticatzione e autorizatzione nen cun comente si faghent in cuncretu. Ddoe at trastos e protocollos medas chi faghet a impreare e su seberu dipendet dae cosas medas, comente su tipu de aplicatzione de isvilupare (un'app pro una banca o pro unu servìtziu mèigu at a tènnere unu livellu de seguresa meda prus artu de s'imbucada a s'àrea de cummentos de unu blog, pro esempru).
Aplicatziones de prus pàginas
In custu atopu semus a in antis a unu situ web traditzionale, fatu de pàginas vàrias, cun un'istadu sarvadu in una sessione. Me is esempros mios apo a fàghere riferimentu a PHP comente linguàgiu ladu-server, ma is pròpios cuntzetos balent cale si siat linguàgiu impreamus.
De sòlitu, sa sessione si mantenet sarvende un'ID comente a cookie (o testimòngiu). Su navigadore imbiat is cookie cun ònnia pedida, duncas su programmadore depet isceti tzerriare session_start ònnia borta chi su script est postu in esecutzione e is datos ant a essi sarvados in cue. Faghet a non sarvare s'ID comente a cookie istudiende un'àtera manera pro dd'imbiare in seguresa.
Paràmetru GET
Sa manera prus sintzilla pro imbiare s'ID de sa sessione est de dd'agiùnghere a sa query string de ònnia pedida, chi duncas at a apàrrere che www.situmiu.com/pagina?PHPSESSID=id-sessione-miu
S'ID matessi faghet a ddu pigare (o impostare) tzerriende sa funtzione session_id. PHP at a pigare s'ID de sa pedida e totu at a funtzionare che cun is cookie ativos. Is prus atentos ant a àere giai bidu un'iscenàriu problemàticu de s'impreu de custa tècnica. Immaginamus chi un'impitadore imbuchet a sa pàgina e ddi pàrgiat de interessu. A custu puntu at a copiare s'URL e dd'at a imbiare a un'amigu o, peus, dd'at a cumpartzire in unu social. Chie at a abèrrere su ligòngiu at a impreare sa pròpiu sessione de su primu impitadore. Si sa sessione cuntenet isceti impostatziones de pagu importu, no at a èssere unu problema, ma si ddoe at datos personales e/o s'ID de s'impitadore chi permitit de imbucare a àreas privadas, custu non ddu podimus permìtere. Diamus a pòdere agiùnghere càncua medida comente s'averìguu de unos cantu datos de s'impitadore (indiritzu IP, user agent e àteru) ma nudda de su chi agatamus in una pedida normale est ùnicu de a beru: duas persones acapiadas cun sa pròpiu versione de su navigadore in sa matessi retze si podent pigare s'unu pro s'àteru.
Paràmetru POST
Pro non cumpartzire sa sessione in pari cun totu is ligòngios, podimus impreare unu mètodu diferente, su de impreare pedidas de tipo POST, is pròpios de is formulàrios (form), e agiùnghere s'ID de sa sessione comente campu cuadu. De sòlitu non faghet a impreare POST pro unu ligòngiu sintzillu, ma cun CSS podimus fàghere unu butone de imbiu (submit) de su totu uguale a unu marcadore <a>. Pro comodidade, faghet a impreare una libreria chi ofèrgiat custa possibilidade. Cun bootstrap bastat a agiùnghere is classes "btn btn-link". In custa manera, ònnia link cumpartzidu at a portare a una pàgina cun una sessione lìmpia. Mancari mègius de sa solutzione cun su paràmetru GET, custa puru portat unos cantu problemas:
- a primu, est un'impreu impròpiu de sa pedida de tipu POST. Non ddoe at acòrdiu si POST si depat impreare pro creare resursas noas o pro ddas modificare, ma pro una visualizatzione est GET su tipu de impreare. Pagu male, comente si siat. Est unu prètziu bonu pro navigare in trancuillidade, chene cookie e chene cumparsa de ventaneddas infadosas;
- su mere etotu de sa sessione torrende a su situ at a agatare una sessione bòida chene atzessu a su profilu suo, a sa pròpiu manera de cando si cantzellant is cookie cun su mètodu clàssicu. Si custu est un'efetu disigiadu pro su contu de sa banca, podet èssere infadosu pro cale si siat impreu prus pagu crìticu;
- s'ID de sa sessione aparet in su còdighe de orìgine de sa pàgina. Custu bolet nàrrere chi sarvende sa pàgina comente a documentu HTML e cumpartzende·ddu cun àteros, su destinatàriu at a tènnere atzessu a sa sessione nostra cun unu simpre clic a subra de unu ligòngiu, torrende in parte a su pròpiu problema de su mètodu de su paràmetru GET.
Paràmetru POST bia JavaScript
Podimus lassare pèrdere su problema n.1 de su puntu passadu ca est isceti chistione de forma, mentres is àteros duos sunt prus de importu pro s'impitadore mèdiu. Ddos podimus arrangiare impreende JavaScript, chi oramai totus lassant ativu, giai chi est in sa base de agiumai totu is prataformas de impreu fitianu.
Pro non passare sa sessione cun su còdighe HTML, creamus un'API chi nd'incumentzet una noa e torret s'ID suo. Su còdighe JavaScript at a impreare s'API pro sarvare s'ID in s'archìviu locale de su navigadore e dd'at a pònnere in su campu de sessione de su formulàriu cando si faghet clic a subra de unu ligòngiu. Cando s'ID est giai in s'archìviu, at a èssere impreadu pro torrare a assetiare sa sessione.
In custa manera, si impreamus AJAX pro ammustrare informatziones de profilu (status de atzessu, nomìngiu de impitadore, etc), s'impitadore at a agatare sa sessione sua chene dèpere torrare a imbucare e, sende chi s'ID s'agiunghet a sa pedida "a bòlidu", no at a apàrrere in su còdighe de orìgine. Su còdighe chi sighit ammustrat custa solutzione, in una versione curtza. Pro semplitzidade, totu s'agatat in unu documentu ùnicu, ma boisàteros regordade·bos de creare semper documentos separados pro PHP, HTML, CSS e JavaScript.
<?php
/* Piga PHPSESSID de is paràmetrus GET e POST
Si su seridori no ddu permitit tocat a passai a manu su balori de PHPSESSID a session_id() */
ini_set('session.use_only_cookies', false);
// No creis su cookie PHPSESSID
ini_set('session.use_cookies', false);
if (isset($_POST['PHPSESSID']) || isset($_POST['get_session_id'])) {
session_start();
}
if (isset($_POST['get_session_id'])) {
echo session_id();
exit();
}
?>
<!doctype html>
<html lang="it">
<head>
<title>Il mio sito senza cookie</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css">
</head>
<body>
<form action="index.php?pagina=link1" method="post">
<input type="hidden" name="PHPSESSID" value="">
<input type="submit" class="btn btn-link" value="Link 1">
</form>
<form action="index.php?pagina=link2" method="post">
<input type="hidden" name="PHPSESSID" value="">
<input type="submit" class="btn btn-link" value="Link 2">
</form>
<p>
Balori de session_id: <span><?php echo session_id() ?: 'NON PRESENTE' ?></span><br>
Sessioi sarvada in su navigadori: <span id="session_js"></span><br>
Si is duus baloris ant a essi ugualis bisitendi is ligòngius, totu funtzionat comenti si depit.
</p>
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
<script>
$(document).ready(function () {
// Circa s'ID de sessioni nell'archiviatzioni de su navigadori
let session_id = window.localStorage.getItem('user_session');
if (session_id === null) {
// L'ID no est sarvau. Si-ndi pedit unu nou
$.post("index.php", {get_session_id: 1})
.done(function(data) {
window.localStorage.setItem('user_session', data);
$('#session_js').html(data);
})
.fail(function() {
alert("Faddina: impossìbili a creai una sessioni");
});
} else {
$('#session_js').html(session_id);
}
$('.btn-link').click(function (e) {
// Clic apitzus de unu de is ligòngius. Agiungi s'ID de sessioni e imbia.
e.preventDefault();
const $form = $(this).parent();
$form.children('input[name="PHPSESSID"]').val(window.localStorage.getItem('user_session'));
$form.submit();
});
});
</script>
</body>
</html>
Cunsideros de seguridade
Sarvare s'ID de sa sessione in s'archiviatzione de su navigadore no est prus pagu seguru de impreare unu cookie. Forsis ni-mancu de prus, cunsideradu chi depimus atentzionare a tècnicas medas de hackeràgiu. S'archiviatzione locale impreat archìvios in su dispositivu de s'impitadore comente acontesset pro is cookie, e lassat chi ddos lègiant isceti pàginas chi benint dae sa pròpiu orìgine. Cale si siat impitadore acapiadu a sa retze depet pigare totu is medidas possìbiles pro evitare atacos de malware a su dispositivu chi nde podent furare datos de importu, inclùdidos is còdighes de sessione.
Is cookie teniant finas a pagos annos a immoe su problema mannu de èssere imbiados cun totu is pedidas a su serbidore, cumprèndidas is non seguras, e duncas chie podiat imbucare a sa retze podiat lèghere totu. Is datos sarvados in livellu locale sunt imbiados a su serbidore isceti cando serbit de a beru, donende prus controllu a su programmadore a subra de su tràficu issoro. Comente si siat, cun s'impreu semper prus ispainadu de HTTPS si depimus orroliare prus pagu chi ddos furent in caminu mentres, comente amus bidu, est ancora pretzisu a evitare de ddos espònnere cando non serbit o faghet mancari dannu.
Concruida
Is cookie fiant unu trastu de importu pro mantènnere s'istadu intre una pedida e s'àtera a su serbidore web a traessu de unu protocollu, HTTP, chi in sese est chene istadu. In sa simpresa issoro ant ammustradu de èssere poderosos e ddos ant impreados pro punnas lutzas, comente a sighire totu is passos de s'atividade de s'impitadore pro nde registrare is fainas, is costumàntzias e a bortas fintzas datos sensìbiles. S'Unione Europea at chircadu de arrangiare sa situatzione ma no at seberadu sa mègius manera. Mancari siat de importu a informare a is impitadores de s'impreu chi si bolet fàghere de is datos issoro e a ddis domandare su permissu, s'agatamus prenos de ventaneddas infadosas a cumparsa pro ònnia navigatzione, cosa peus pro chie at cunfiguradu su navigadore pro nde cantzellare is datos de navigatzione essende. In prus, non podimus èssere seguros chi sitos malos rispetent su seberu nostru, duncas abarrat de importu chi s'impitadore atentzionet a su chi abarrat sarvadu in su dispositivu. Diat a èssere istadu forsis mègius a tipizare is cookie e donare a s'impitadore sa manera de cunfigurare una borta pro semper su cumportamentu de su navigadore pro ònnia tipu, permitende etzetziones in manera prus permitidora o prus severa. Ddoe diat at a èssere unu controllu prus standardizadu e una navigatzione prus lèbia, ma paret chi oramai s'idea siat sa de abbandonare is cookie de su totu mancari, comente naradu, ddoe siant tècnicas de sighidura prus bonas e prus moitzas.
Si s'arribat a unu web chene cookie diat a èssere mègius a tènnere unu campu standard pro s'ID de sa sessione in sa pròssima versione de HTTP, ma comente amus bidu in custu artìculu est giai possìbile a no impreare cookie, arrangende·si cun su chi tenimus.
Cummenta