<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>jblog &#187; Apache</title>
	<atom:link href="http://jblog.it/category/apache/feed" rel="self" type="application/rss+xml" />
	<link>http://jblog.it</link>
	<description>News e appunti per webmaster</description>
	<lastBuildDate>Tue, 25 May 2010 16:16:12 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Autenticazione HTTP &#8220;basic&#8221; su server Apache</title>
		<link>http://jblog.it/2010/01/11/autenticazione-http-basic-server-apache-mod_auth-htaccess-htpasswd-proteggere-file-directory_818.html</link>
		<comments>http://jblog.it/2010/01/11/autenticazione-http-basic-server-apache-mod_auth-htaccess-htpasswd-proteggere-file-directory_818.html#comments</comments>
		<pubDate>Mon, 11 Jan 2010 05:00:01 +0000</pubDate>
		<dc:creator>Giacomo</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Sicurezza]]></category>
		<category><![CDATA[mod_auth]]></category>
		<category><![CDATA[proteggere directory]]></category>
		<category><![CDATA[proteggere file]]></category>
		<category><![CDATA[proteggere login]]></category>
		<category><![CDATA[sicurezza apache]]></category>
		<category><![CDATA[sicurezza directory]]></category>
		<category><![CDATA[sicurezza file]]></category>

		<guid isPermaLink="false">http://jblog.it/?p=818</guid>
		<description><![CDATA[L'autenticazione HTTP permette di implementare un controllo degli accessi basato su username e password, semplice da realizzare, stabile e sicuro. In questo articolo: come proteggere file e directory con username e password. Infine, come personalizzare la pagina di errore 401.]]></description>
			<content:encoded><![CDATA[<p><a title="Autenticazione HTTP “basic” su server Apache" href="http://jblog.it/2010/01/11/autenticazione-http-basic-server-apache-mod_auth-htaccess-htpasswd-proteggere-file-directory_818.html"><img src="http://jblog.it/wp-content/uploads/2010/01/apachesecurity_bouncer.jpg" alt="apachesecurity bouncer Autenticazione HTTP basic su server Apache" width="540" height="322" title="Autenticazione HTTP basic su server Apache" /></a></p>
<p>Ogni applicazione viene progettata e sviluppata con uno o più sistemi di autenticazione e sicurezza. Pensiamo al login di un sito web, al controllo degli utenti o alla gestione dei permessi.</p>
<p>L&#8217;autenticazione HTTP permette di implementare un controllo degli accessi basato su username e password, semplice da realizzare, stabile e sicuro.</p>
<p><strong class="highlight_green">PRO.</strong> Questo tipo di autenticazione offre un più rigido controllo sugli utenti e una maggiore stabilità rispetto al classico login. Il controllo degli utenti è <strong>molto rigido</strong> in quanto è l&#8217;amministratore a inserire nuove coppie di username e password, al contrario della procedura di registrazione durante la quale sono gli utenti a inserire i dati. Riguardo la <strong>stabilità</strong>, il discorso è molto simile a quello che si fa con i cms: un modulo Apache scritto e controllato da centinaia di sviluppatori è assai meno probabile che fallisca rispetto alle procedure di login scritte da un team ristretto di programmatori.</p>
<p><span id="more-818"></span><strong class="highlight_red">CONTRO.</strong> Il primo limite sta proprio nel fatto che per inserire un nuovo utente bisogna andare a scrivere &#8220;a mano&#8221; i dati per l&#8217;autenticazione, problema comunque risolvibile con uno script che accede al file dei dati per l&#8217;autenticazione, nel caso si voglia una procedura di registrazione automatizzata. Un altro limite è la difficoltà di gestire l&#8217;utente connesso, ad esempio, per avere un&#8217;area personale o per memorizzare i prodotti del carrello, tutte cose facilmente realizzabili nel caso di un login con database.</p>
<p><strong>AUTENTICAZIONE HTTP con PHP » <a href="http://php.net/manual/en/features.http-auth.php" target="_blank">http://php.net/manual/en/features.http-auth.php</a></strong></p>
<p><span class="highlight_orange"><strong>ATTENZIONE.</strong> Potrebbe succedere che <strong>in locale</strong> l&#8217;autenticazione HTTP non funzioni. Invece di perdere tempo inutilmente provala direttamente sul tuo spazio web, magari in una directory di test. A me è successo così! Per saperne di più segui <a href="http://forum.html.it/forum/showthread.php?s=&amp;threadid=1376669" target="_blank">questa discussione sul forum di html.it</a> che, tutt&#8217;ora non ha risposte <img src='http://jblog.it/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' title="Autenticazione HTTP basic su server Apache" /> .</span></p>
<h4>SOMMARIO</h4>
<dl>
<dt><strong><a href="#buon-motivo-autenticazione-http">Un buon motivo per l’autenticazione HTTP</a></strong></dt>
<dd><small>Una delle tante situazioni che ti dovrebbe far capire il senso dell&#8217;autenticazione HTTP.</small></dd>
<dt><strong><a href="#diverse-autenticazioni-http">Le diverse autenticazioni HTTP</a></strong></dt>
<dd><small>La differenza fra le diverse autenticazioni.</small></dd>
<dt><strong><a href="#esempio-veloce">Un esempio veloce</a></strong></dt>
<dd><small>Esempio facile da capire per introdurre l&#8217;argomento.</small></dd>
<dt><strong><a href="#direttive-apache">Le direttive Apache</a></strong></dt>
<dd><small>Una panoramica sulle direttive Apache che servono per implementare l&#8217;autenticazione HTTP, in modo da comprendere meglio cosa stiamo facendo.</small></dd>
<dt><strong><a href="#ottenere-percorso-assoluto">Ottenere il percorso assoluto</a></strong></dt>
<dd><small>Conoscere il percorso assoluto del server è necessario per impostare correttamente il file .htaccess.</small></dd>
<dt><strong><a href="#file-htpasswd">Il file delle password: .htpasswd</a></strong></dt>
<dd><small>Il file che contiene le coppie &#8220;username:password&#8221;.</small></dd>
<dt><strong><a href="#file-htgroup">Il file dei gruppi di utenti: .htgroup</a></strong></dt>
<dd><small>Il file (opzionale) in cui impostare i gruppi di utenti.</small></dd>
<dt><strong><a href="#autenticazione-http-in-pratica">Autenticazione HTTP in pratica</a></strong></dt>
<dd>
<div style="padding-left: 10px;"><small><a href="#proteggere-file">Come proteggere i file</a><br />
<a href="#proteggere-directory">Come proteggere una directory</a><br />
<a href="#nota-prestazioni">Una nota sulle prestazioni</a><br />
<a href="#creare-eccezioni">Creare eccezioni</a></small></div>
</dd>
<dt><strong><a href="#pagina-errore-401">Personalizza la pagina di errore “401 Authorization Required”</a></strong></dt>
<dd><small>Come personalizzare la pagina di errore che appare quando non si inseriscono i dati corretti.</small></dd>
</dl>
<h5>Note sull&#8217;articolo</h5>
<p>Data la complessità degli argomenti trattati cerco di dare il giusto supporto anche agli sviluppatori che si sono avvicinati da poco all&#8217;uso del server Apache. Infatti per buona parte dell&#8217;articolo vengono fornite tutte quelle conoscenze di base richieste per una buona comprensione dell&#8217;autenticazione HTTP al fine di <strong>evitare un semplice copia-incolla</strong> che difficilmente porterà ai risultati sperati.</p>
<p><strong>Se le direttive e il funzionamento del server Apache ti sono familiari</strong> puoi benissimo andare direttamente a vedere come implementare l&#8217;autenticazione HTTP iniziando a leggere dal paragrafo &#8220;<a title="Autenticazione HTTP in pratica" href="#autenticazione-http-in-pratica">Autenticazione HTTP in pratica</a>&#8220;.</p>
<h2 id="buon-motivo-autenticazione-http">Un buon motivo per l&#8217;autenticazione HTTP</h2>
<p>Pensa a un grosso sito ecommerce. Questo sarà diviso almeno in 4 aree: publica, utenti, gestione, amministrazione.</p>
<p>Nell&#8217;area <em>pubblica</em> potranno accedervi tutti, nell&#8217;area <em>utenti</em> solo gli utenti registrati, nell&#8217;area <em>gestione</em> solo gli addetti alle normali mansioni, come la moderazione dei commenti sui prodotti, e nell&#8217;area <em>amministrazione</em> solo pochi amministratori che, tra gli altri, avranno il compito di aggiungere nuovi amministratori e gestirne i permessi. Data la delicatezza dell&#8217;area <em>amministrazione</em> è necessario proteggerla il più possibile.</p>
<p>Ed è qui che entra in gioco l&#8217;autenticazione HTTP, che verrà implementata per creare una <strong>ulteriore barriera</strong> prima di accedere alla pagina <em>login</em>. In questo modo per accedere all&#8217;area <em>amministrazione</em> sarà necessario inserire due <strong>diverse</strong> coppie di username e password, con il conseguente rafforzamento della sicurezza.</p>
<p><img class="alignnone size-full wp-image-820" title="esempio ecommerce autenticazione http" src="http://jblog.it/wp-content/uploads/2010/01/example_http_sitemap.jpg" alt="example http sitemap Autenticazione HTTP basic su server Apache" width="540" height="276" /></p>
<p>Naturalmente, questo è solo uno dei tanti motivi per sfruttare l&#8217;autenticazione HTTP per rendere più sicuro il proprio sito.</p>
<h2 id="diverse-autenticazioni-http">Le diverse autenticazioni HTTP</h2>
<p>Su un server Apache si possono implementare almeno 3 tipi di autenticazione HTTP.</p>
<p><strong>Base.</strong> Utilizza dei file di testo per l&#8217;autenticazione. Il modulo necessario è <strong>mod_auth.c</strong>, ed è considerato uno dei moduli di base. In ogni caso dai un&#8217;occhiata ai servizi del tuo provider oppure alle informazioni php, con la funzione <em>phpinfo()</em>.</p>
<p><strong>DBM.</strong> Utilizza dei file di tipo DBM per l&#8217;elenco di username e password. Il modulo necessario è <strong>mod_auth_dbm.c</strong>.</p>
<p><strong>Digest.</strong> Basata sull&#8217;algoritmo di hashing md5.  Il modulo necessario è <strong>mod_auth_digest.c</strong>. Questo modulo  è ancora in fase di test e alcune funzioni non sono ancora correttamente implementate.</p>
<h2 id="esempio-veloce">Un esempio veloce</h2>
<p>Per darti l&#8217;idea di quello che dobbiamo fare ti faccio un esempio veloce.</p>
<h5 id="httpauthbase_ex1">File .htaccess</h5>
<pre>AuthType Basic
AuthName "Restricted Files" #messaggio personalizzato
AuthUserFile /percorso-assoluto/.htpasswd
Require valid-user</pre>
<p><small>N.B. non ho scritto il vero percorso assoluto per questioni di sicurezza. Credo che il mio provider non vorrebbe che lo sventolassi in giro! <img src='http://jblog.it/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' title="Autenticazione HTTP basic su server Apache" />  </small></p>
<h5 id="httpauthbase_ex2">File .htpasswd</h5>
<pre>admin:86dGPOHvD26i2
admin2:165491czyZTp2
admin3:29p7hc19vPpm6</pre>
<p>dove username e password della prima riga sono &#8220;admin&#8221;.</p>
<h5>Demo</h5>
<p>Se non ti basta lo screenshot puoi provarlo andando su <a href="http://test.jblog.it/http_auth_base/" target="_blank">http://test.jblog.it/http_auth_base/</a> (username e password sono entrambe &#8220;admin&#8221;).</p>
<p><img class="alignnone size-full wp-image-821" title="richiesta dati autenticazione http" src="http://jblog.it/wp-content/uploads/2010/01/screenshot_httpauth.jpg" alt="screenshot httpauth Autenticazione HTTP basic su server Apache" width="540" height="275" /></p>
<h2 id="direttive-apache">Le direttive Apache</h2>
<p>Le direttive principali per implementare l&#8217;autenticazione HTTP.</p>
<p><strong>AuthType.</strong> Imposta il tipo di autenticazione: basic o digest.</p>
<p><strong>AuthName.</strong> Messaggio o descrizione personalizzata; utile per dare indicazioni.</p>
<p><strong>AuthUserFile.</strong> File degli username e delle password, generalmente chiamato .htpasswd.</p>
<p><strong>AuthGroupFile.</strong> File dei gruppi di utenti.</p>
<p><strong>Require.</strong> Filtra gli utenti abilitati all&#8217;accesso. Generalmente si utilizza <em>valid-user</em> per indicare che l&#8217;accesso è permesso a tutti gli utenti validi, ad esempio quelli che inseriscono credenziali valide. Alternativamente si possono utilizzare <em>user</em> e <em>group</em> seguiti rispettivamente da una lista di utenti o di gruppi, separati da spazi.</p>
<p><strong>Satisfy.</strong> Gestisce la politica degli accessi. Funziona solo se sono utilizzate contemporaneamente le direttive <em>Allow</em> e <em>Require</em>. Con <em>All</em> fa in modo che entrambe le condizioni siano verificate per convalidare l&#8217;accesso, invece con <em>Any</em> basta che sia verificata solo una delle condizioni.</p>
<h2 id="ottenere-percorso-assoluto">Ottenere il percorso assoluto</h2>
<p>Per collegare il file delle password (.htpasswd) e dei gruppi al file .htaccess non ci si può limitare al percorso relativo, ma è necessario il <strong>percorso assoluto</strong>. Per internderci, il percorso assoluto è quello che sul nostro pc inizia con &#8220;C:/&#8230;&#8221;.</p>
<p>Uno dei modi per ottenere il percorso assoluto del server è quello di creare ed eseguire il seguente <strong>script php</strong>:</p>
<pre>&lt;?php
   echo $_SERVER['DOCUMENT_ROOT'];
?&gt;</pre>
<p>dove la variabile <code>$_SERVER['DOCUMENT_ROOT']</code> contiene il percorso assoluto della directory in cui si trovano i file del tuo sito.</p>
<h4>Se non sei pratico/a di php segui queste istruzioni</h4>
<ol>
<li>Rinomina lo script in &#8220;doc_root.php&#8221;</li>
<li>Caricalo nella directory principale del tuo sito</li>
<li>Eseguilo scrivendo http://www.tuosito.com/doc_root.php</li>
<li> Copia e conserva il testo fornito in output, cioè il percorso assoluto</li>
</ol>
<p><img class="alignnone size-full wp-image-825" title="percorso assoluto | document root" src="http://jblog.it/wp-content/uploads/2010/01/doc_root.jpg" alt="doc root Autenticazione HTTP basic su server Apache" width="540" height="161" /></p>
<p><strong>ATTENZIONE.</strong> Ti accorgerai anche tu che il percorso ottenuto dallo script php <strong>non è completo</strong>. Basterà guardare alla fine per osservare l&#8217;assenza del nome della directory in cui si trova il file .htpasswd. Quasi sempre è necessario <strong>completare il percorso assoluto</strong> scrivendo manualmente la directory in cui si trova il file .htpasswd. Un po&#8217; di pazienza e tutto funzionerà a dovere! <img src='http://jblog.it/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' title="Autenticazione HTTP basic su server Apache" /> </p>
<h2 id="file-htpasswd">Il file delle password: .htpasswd</h2>
<p>Il  file .htpasswd deve contenere la lista di username e password che verranno utilizzati per l&#8217;autenticazione (vedi l&#8217;esempio in basso).</p>
<p><strong>Il nome del file.</strong> Il file dei dati di autenticazione puoi rinominarlo a tuo piacimento; non è obbligatorio chiamarlo &#8220;.htpasswd&#8221;. Tuttavia è consigliabile rispettare il modello &#8220;.htxxxxxx&#8221;, cioè farlo iniziare sempre con &#8220;.ht&#8221; cambiando solo il resto. Esempi validi: &#8220;.htpassword&#8221;, &#8220;.ht_dati_accesso&#8221;.</p>
<p><strong>Criptare le password.</strong> Al contrario dell&#8217;username, che viene scritto &#8220;in chiaro&#8221;, la password deve essere criptata. Fortunatamente su internet si possono trovare molti siti che si occupano non solo di criptare la password ma anche di impostare il file .htpasswd.</p>
<h5>Strumenti utili per .htpasswd</h5>
<p><a href="http://www.htaccesstools.com/htpasswd-generator/" target="_blank">http://www.htaccesstools.com/htpasswd-generator/</a><br />
<a href="http://www.wmtips.com/tools/htpasswd-generator/" target="_blank">http://www.wmtips.com/tools/htpasswd-generator/</a><br />
<a href="http://www.4webhelp.net/us/password.php" target="_blank">http://www.4webhelp.net/us/password.php</a><br />
<a href="http://www.clockwatchers.com/htaccess_tool.html" target="_blank">http://www.clockwatchers.com/htaccess_tool.html</a><br />
<a href="http://htmlfixit.com/cgi-bin/tools/htaccess/index.pl" target="_blank">http://htmlfixit.com/cgi-bin/tools/htaccess/index.pl</a><br />
<a href="http://tools.dynamicdrive.com/password/" target="_blank">http://tools.dynamicdrive.com/password/</a><br />
<a href="http://www.softspecialist.com/i/htaccess-password-generator-htpasswd-encryption-tool.htm" target="_blank">http://www.softspecialist.com/i/htaccess-password-generator-htpasswd-encryption-tool.htm</a></p>
<p><strong>Per iniziare.</strong> Se non ti va o non riesci a  utilizzare questi tools puoi iniziare subito con questi dati: <span style="font-family: Courier New;">admin:86dGPOHvD26i2</span>, dove username e password sono entrambi admin.</p>
<p><strong>Scrivere il file .htpasswd. </strong>Per creare un file .htpasswd è necessario seguire solo <strong>2 semplici regole</strong>:</p>
<ol>
<li> username e password devono essere separate dai due punti &#8220;:&#8221;</li>
<li>inserire una coppia <code>&lt;username&gt;:&lt;password&gt;</code> per riga</li>
</ol>
<h5>Esempio di file .htpasswd</h5>
<pre>admin:86dGPOHvD26i2
admin2:165491czyZTp2
admin3:29p7hc19vPpm6</pre>
<p><span class="highlight_red"><strong>Per una maggior sicurezza</strong> sulla documentazione Apache viene consigliato di inserire i file .htpasswd all&#8217;esterno della directory principale del sito in modo da renderli totalmente inaccessibili dall&#8217;esterno, ad esempio tramite browser. Purtroppo non sempre è possibile inserire dei file all&#8217;esterno della directory principale, soprattutto se hai un hosting di base.</span></p>
<h2 id="file-htgroup">Il file dei gruppi di utenti: .htgroup</h2>
<p>Il  file dei gruppi di utenti deve contenere l&#8217;elenco dei gruppi in corrispondenza dei quali si scrive la lista di username appartenenti (vedi l&#8217;esempio in basso). Questo file è <strong>direttamente collegato al file .htpasswd</strong> in quanto gli username appartenenti a ciascun gruppo sono proprio quelli scritti nel file .htpasswd.</p>
<p><strong>Il nome del file.</strong> Il file dei dati di autenticazione puoi rinominarlo a tuo piacimento. Tuttavia è consigliabile rispettare il modello &#8220;.htxxxxxx&#8221;, cioè farlo iniziare sempre con &#8220;.ht&#8221; cambiando solo il resto. Esempi validi: &#8220;.htgruppi&#8221;, &#8220;.ht_lista_gruppi&#8221;. Ho preferito chiamarlo &#8220;.htgroup&#8221; per avere una maggior chiarezza nella scrittura dell&#8217;articolo.</p>
<p><strong>A cosa serve?</strong> Dividere gli utenti per gruppi è necessario, ad esempio, nel caso in cui si hanno diverse aree alle quali devono accedere diversi gruppi di utenti. Inoltre è anche comodo per la direttiva <em>Require </em>perché invece di inserire tutti gli username si evita di &#8220;sporcare&#8221; eccessivamente il file .htaccess limitandosi a scrivere pochi gruppi.</p>
<p><img class="alignnone size-full wp-image-822" title="relazioni e flusso htaccess htpasswd htgroup" src="http://jblog.it/wp-content/uploads/2010/01/http_auth_flow.jpg" alt="http auth flow Autenticazione HTTP basic su server Apache" width="540" height="211" /></p>
<h4>Esempio</h4>
<p>Nota la &#8220;pulizia&#8221; della <em>versione 2</em> del file .htaccess rispetto alla <em>versione 1</em>. Probabilmente non ti sembrerà niente di così rivoluzionario&#8230; Pensa in grande! Pensa a una lista di 30 username per ogni gruppo!</p>
<h5>File .htpasswd (valido per le due versioni del file .htaccess)</h5>
<pre>admin:86dGPOHvD26i2
admin2:165491czyZTp2
admin3:29p7hc19vPpm6
admin4:86dGPOHvD26i2
admin5:165491czyZTp2
admin6:29p7hc19vPpm6
admin7:86dGPOHvD26i2
admin8:165491czyZTp2
admin9:29p7hc19vPpm6</pre>
<h5>File .htaccess [versione 1] (senza dividere gli utenti in gruppi)</h5>
<pre>&lt;Files index_gruppo1.php&gt;
   AuthType Basic
   AuthName "Fai parte del gruppo 1?"
   AuthUserFile /percorso_assoluto/.htpasswd
   AuthGroupFile /percorso_assoluto/.htgroup
   Require user admin admin2 admin3 admin4 admin5
&lt;/Files&gt;

&lt;Files index_gruppo2.php&gt;
   AuthType Basic
   AuthName "Fai parte del gruppo 2?"
   AuthUserFile /percorso_assoluto/.htpasswd
   AuthGroupFile /percorso_assoluto/.htgroup
   Require user admin6 admin7 admin8 admin9
&lt;/Files&gt;</pre>
<h5>File .htaccess [versione 2] (utenti suddivisi in gruppi)</h5>
<pre>&lt;Files index_gruppo1.php&gt;
   AuthType Basic
   AuthName "Fai parte del gruppo 1?"
   AuthUserFile /percorso_assoluto/.htpasswd
   AuthGroupFile /percorso_assoluto/.htgroup
   Require group gruppo1
&lt;/Files&gt;

&lt;Files index_gruppo2.php&gt;
   AuthType Basic
   AuthName "Fai parte del gruppo 2?"
   AuthUserFile /percorso_assoluto/.htpasswd
   AuthGroupFile /percorso_assoluto/.htgroup
   Require group gruppo2
&lt;/Files&gt;</pre>
<h5>.htgroup (per il file .htaccess versione 2)</h5>
<pre>gruppo1: admin admin2 admin3 admin4 admin5
gruppo2: admin6 admin7 admin8 admin9</pre>
<p><span class="highlight_green"><strong>Demo.</strong> Per farti capire meglio di cosa sto parlando vai su <a href="http://test.jblog.it/http_auth_group/" target="_blank">http://test.jblog.it/http_auth_group/</a>.</span></p>
<p><span class="highlight_red"><strong>Per una maggior sicurezza</strong> sulla documentazione Apache viene consigliato di inserire i file .htgroup all&#8217;esterno della directory principale del sito in modo da renderli totalmente inaccessibili dall&#8217;esterno, ad esempio tramite browser. Purtroppo non sempre è possibile inserire dei file all&#8217;esterno della directory principale, soprattutto se hai un hosting di base.</span></p>
<h2 id="autenticazione-http-in-pratica">Autenticazione HTTP in pratica</h2>
<p><!--adv300--></p>
<h3 id="proteggere-file">Come proteggere i file</h3>
<p>Per proteggere uno o più file si possono utilizzare le direttive <code>&lt;Files&gt;</code> o <code>&lt;FilesMatch&gt;</code>.</p>
<p>La seconda è da preferire quando i file da proteggere si devono riconoscere tramite regex. In pratica, la <strong>direttiva <code>&lt;FilesMatch&gt;</code></strong> deve essere utilizzata quando  si devono proteggere più file con gli stessi criteri oppure quando non si è sicuri del nome, ad esempio quando non si sa se l&#8217;estensione è scritta in minuscolo o in maiuscolo.</p>
<p>La <strong>direttiva <code>&lt;Files&gt;</code></strong> è da preferire solo quando il file è uno solo e si è sicuri del nome.</p>
<h5>Uso della direttiva &lt;FilesMatch&gt;</h5>
<pre># 1) protegge i file secret1.php e secret2.php
# 2) [pP][hH][pP] perchè non si è sicuri di come è scritta l'estensione
&lt;FilesMatch "(secret1|secret2)\.[pP][hH][pP]"&gt;
   AuthType Basic
   AuthName "Accesso alle pagine segrete..."
   AuthUserFile /percorso_assoluto/.htpasswd
   Require valid-user
&lt;/FilesMatch&gt;</pre>
<h5>Uso della direttiva &lt;Files&gt;</h5>
<pre>&lt;Files secret1.php&gt;
   AuthType Basic
   AuthName "Accesso alla pagina segreta..."
   AuthUserFile /percorso_assoluto/.htpasswd
   Require valid-user
&lt;/Files&gt;

&lt;Files secret2.php&gt;
   AuthType Basic
   AuthName "Accesso alla pagina segreta..."
   AuthUserFile /percorso_assoluto/.htpasswd
   Require valid-user
&lt;/Files&gt;</pre>
<h3 id="proteggere-directory">Come proteggere una directory</h3>
<p>Teoricamente si dovrebbe agire come per i file, utilizzando però le direttive <code>&lt;Directory&gt;</code> e <code>&lt;DirectoryMatch&gt;</code>.</p>
<p><strong>Problema. </strong>A meno che tu non abbia accesso al file di configurazione del server o del virtual host, non è possibile farlo in quanto le direttive <code>&lt;Directory&gt;</code> e <code>&lt;DirectoryMatch&gt;</code> <strong>NON possono essere utilizzate nel file .htaccess</strong>. A questo proposito vorrei ringraziare Enoa del <a title="Come utilizzare le direttive &lt;Directory&gt; e &lt;DirectoryMatch&gt;?" href="http://forum.html.it/forum/showthread.php?s=&amp;threadid=1376012" target="_blank">forum di html.it</a>.</p>
<p><strong>Soluzione. </strong>Inserire un file .htaccess direttamente nelle directory da proteggere. Tutto qui! <img src='http://jblog.it/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' title="Autenticazione HTTP basic su server Apache" />  Ricordati di non inserire i file .htpasswd e .htgroup nella directory da proteggere.</p>
<h5>Esempio di file .htaccess da inserire nella directory da proteggere</h5>
<pre>AuthType Basic
AuthName "Accesso alla Directory XXX..."
AuthUserFile /percorso_assoluto/.htpasswd
Require valid-user</pre>
<h3 id="nota-prestazioni">Una nota sulle prestazioni</h3>
<p>Per sua natura l&#8217;implementazione dell&#8217;autenticazione HTTP comporta un <strong>leggero peggioramento delle prestazioni</strong>. In pratica, ogni volta che si accede a dei file protetti direttamente o indirettamente (cioè all&#8217;interno di una directory protetta) il server controlla se la richiesta HTTP è autorizzata ad essere soddisfatta. In altre parole, ogni &#8211; e sottolineo ogni &#8211; richiesta HTTP è soggetta a un controllo da parte del server per verificare se questa possiede le autorizzazioni necessarie.</p>
<p>Quindi, prima di implementare un&#8217;autenticazione HTTP chiediti quanto influirà questo, seppur leggero, abbassamento di prestazioni.</p>
<h3 id="creare-eccezioni">Creare eccezioni</h3>
<p>Nonostante ci si autentichi con successo potrebbero sorgere altri problemi. Gli script utilizzati con <strong>tecniche Ajax</strong> oppure i file <strong>XML</strong> richiamati da animazioni Flash potrebbero non essere letti in quanto la richiesta di questi file non proverrebbe dal browser con cui ci si è autenticati e il server Apache potrebbe considerarla come una <strong>richiesta non autorizzata</strong>.</p>
<p>Un&#8217;altra situazione per la quale è necessario creare delle eccezioni si ha quando ci sono dei <strong>file o sottodirectory ad accesso libero in una directory protetta</strong>.</p>
<h4><strong>Soluzione veloce</strong></h4>
<p>Se il sito è stato <strong>sviluppato completamente da te</strong>, non avrai grosse difficoltà ad applicare questa soluzione: ti basterà solo modificare qualche riga di codice.</p>
<p>Inserire i file ad accesso libero in una <strong>sottodirectory da &#8220;liberare&#8221;</strong> dalla protezione dell&#8217;autenticazione HTTP.</p>
<ol>
<li>Crea una sottodirectory</li>
<li>Inserisci tutti i file e le directory da &#8220;liberare&#8221;</li>
<li>Inserisci in questa sottodirectory un nuovo file .htaccess con il seguente codice</li>
</ol>
<pre>Allow from All
Satisfy Any</pre>
<p>Queste due righe disattivano l&#8217;inserimento dei dati per l&#8217;autenticazione. Con <code>Satisfy Any</code> si stabilisce che è sufficiente verificare una delle due condizioni tra <code>Require</code> (che si trova nel file .htaccess della directory superiore) e <code>Allow</code>. Quindi, poiché con <code>Allow from All</code> diciamo ad server che l&#8217;accesso è &#8220;permesso a tutti&#8221; una delle due direttive è sempre verificata.</p>
<h4>Soluzione complessa</h4>
<p>Se il sito è <strong>basato su un CMS</strong> o comunque <strong>non è stato sviluppato da te</strong> non è possibile spostare file e directory in quanto non sapremmo dove effettuare le modifiche al codice. Questa soluzione infatti permette di &#8220;liberare&#8221; file e directory lasciandoli tutti al loro posto.</p>
<p><strong>Liberare una directory</strong>. Come per la soluzione veloce,  basta inserire al suo interno un nuovo file .htaccess con il seguente codice:</p>
<pre>Allow from All
Satisfy Any</pre>
<p><strong>Liberare uno o più file. </strong>Utilizzando le direttive <code>&lt;Files&gt;</code> o <code>&lt;FilesMatch&gt;</code> è possibile liberare rispettivamente uno o più files. Utilizzare <code>&lt;Files&gt;</code> per liberare dei file in base al <strong>nome esatto</strong> mentre<code> &lt;FilesMatch&gt;</code> per liberare dei file riconoscendoli tramite espressioni regolari.</p>
<p><strong>Il file index.php.</strong> Generalmente se si accede a una directory senza specificare un file verremo portati sul file index.php o index.html. Se liberiamo il file index.php della directory contenente il file .htaccess principale (con le varie istruzioni per l&#8217;autenticazione HTTP) questo è soggetto a un doppio comportamento. Se accediamo alla directory (senza specificare nessun file), cioè scrivendo nel browser &#8220;http://miosito.com/directory_protetta/&#8221; ci verranno chiesti i dati per l&#8217;autenticazione. Invece se accediamo al file index.php (specificandolo nell&#8217;indirizzo), cioè scrivendo nel browser &#8220;http://miosito.com/directory_protetta/index.php&#8221; non ci vengono chiesti i dati per l&#8217;autenticazione. Non credo sia possibile risolvere questo problema.</p>
<p><strong>Demo.</strong> Prova le eccezioni create per index.php e free_access.php con questo script: <a href="http://test.jblog.it/http_auth_exception/index.php" target="_blank">http://test.jblog.it/http_auth_exception/index.php</a>. Prova anche ad accedere a <a href="http://test.jblog.it/http_auth_exception/" target="_blank">http://test.jblog.it/http_auth_exception/</a> in cui, a differenza del primo indirizzo, ti verranno chiesti i dati per l&#8217;autenticazione.</p>
<h5>Esempio</h5>
<pre>AuthType Basic
AuthName "Accesso alla Directory..."
AuthUserFile /percorso_assoluto/.htpasswd
Require valid-user

# Libera il file index.php
&lt;Files index.php&gt;
   Allow from All
   Satisfy Any
&lt;/Files&gt;

# Libera il file free_access.php
&lt;Files free_access.php&gt;
   Allow from All
   Satisfy Any
&lt;/Files&gt;
# Libera tutti i file .xml, .css e .js
&lt;FilesMatch "\.(xml|css|js)$"&gt;
   Allow from All
   Satisfy Any
&lt;/FilesMatch&gt;

# Libera i file "page1.php" e "page2.php"
&lt;FilesMatch "^(page1\.php|page2\.php)$"&gt;
   Allow from All
   Satisfy Any
&lt;/FilesMatch&gt;</pre>
<h2 id="pagina-errore-401">Personalizza la pagina di errore &#8220;401 Authorization Required&#8221;</h2>
<p>Come ciliegina sulla torta <img src='http://jblog.it/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' title="Autenticazione HTTP basic su server Apache" />  impostiamo una <strong>pagina personalizzata</strong> per l&#8217;errore 401 che si verifica quando non si inseriscono dei dati di autenticazione corretti.</p>
<h5>Pagina 401 di default</h5>
<p><img class="alignnone size-full wp-image-823" title="pagina errore 401 default | authentication required" src="http://jblog.it/wp-content/uploads/2010/01/http_auth_401default.jpg" alt="http auth 401default Autenticazione HTTP basic su server Apache" width="540" height="236" /></p>
<h5>Codice da inserire nel file .htaccess principale</h5>
<pre>ErrorDocument 401 /my_401.html</pre>
<h5>La mia pagina 401 personalizzata</h5>
<p><img class="alignnone size-full wp-image-824" title="pagina errore 401 personalizzata | authentication required" src="http://jblog.it/wp-content/uploads/2010/01/http_auth_401custom.jpg" alt="http auth 401custom Autenticazione HTTP basic su server Apache" width="540" height="236" /></p>
<p><strong>Demo.</strong> Prova la pagina personalizzata su <a href="http://test.jblog.it/http_auth_errordoc/" target="_blank">http://test.jblog.it/http_auth_errordoc/</a> (clicca su &#8220;annulla&#8221;).</p>
<h2>Suggerimenti? Bisogno d&#8217;aiuto?</h2>
<p>Sto imparando a mie spese che su Apache anche le cose più semplici non sono così immediate, ma bisogna sempre sbatterci un po&#8217; la testa!</p>
<p>Se hai dei suggerimenti per una miglior comprensione dell&#8217;articolo, ti serve qualche chiarimento o non riesci a venire a capo di un particolare problema non esitare a contattarmi. Sarà l&#8217;occasione per imparare qualcosa di nuovo!</p>
<h2>Crediti</h2>
<p>Apache HTTP Server &#8211; Core » <a href="http://httpd.apache.org/docs/2.0/mod/core.html" target="_blank">http://httpd.apache.org/docs/2.0/mod/core.html</a></p>
<p>Apache HTTP Server &#8211; mod_auth » <a href="http://httpd.apache.org/docs/2.0/mod/mod_auth.html" target="_blank">http://httpd.apache.org/docs/2.0/mod/mod_auth.html</a></p>
<p>Apache HTTP Server &#8211; Authentication, Authorization and Access Control » <a href="http://httpd.apache.org/docs/2.0/howto/auth.html" target="_blank">http://httpd.apache.org/docs/2.0/howto/auth.html</a></p>
<p>Foto | NYkette » <a href="http://newyorkette.com/2006/03/08/a-bouncer-on-bouncers/" target="_blank">http://newyorkette.com/2006/03/08/a-bouncer-on-bouncers/</a></p>
<img src="http://jblog.it/?ak_action=api_record_view&id=818&type=feed" alt=" Autenticazione HTTP basic su server Apache"  title="Autenticazione HTTP basic su server Apache" />]]></content:encoded>
			<wfw:commentRss>http://jblog.it/2010/01/11/autenticazione-http-basic-server-apache-mod_auth-htaccess-htpasswd-proteggere-file-directory_818.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Ridurre le richieste HTTP (parte 1): come utilizzare la cache del browser</title>
		<link>http://jblog.it/2009/04/24/ridurre-richieste-http-come-utilizzare-cache-browser_124.html</link>
		<comments>http://jblog.it/2009/04/24/ridurre-richieste-http-come-utilizzare-cache-browser_124.html#comments</comments>
		<pubDate>Fri, 24 Apr 2009 20:56:12 +0000</pubDate>
		<dc:creator>Giacomo</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Ottimizzazione]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[meta]]></category>
		<category><![CDATA[mod_expires]]></category>
		<category><![CDATA[mod_headers]]></category>
		<category><![CDATA[ottimizzare]]></category>
		<category><![CDATA[richieste http]]></category>

		<guid isPermaLink="false">http://jblog.it/?p=124</guid>
		<description><![CDATA[Iniziamo una lunga serie di articoli sull&#8217;ottimizzazione dei siti web in cui verranno trattate le tecniche e i suggerimenti per rendere efficiente il proprio sito web.
In questo articolo parlo della cache dei browser, come e perché gestirla. Vedrai cos&#8217;è una richiesta http, un&#8217;intestazione http e le tre tecniche principali per istruire il browser su come dovrà [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://jblog.it/2009/04/24/ridurre-richieste-http-come-utilizzare-cache-browser_124.html"><img class="alignright size-full wp-image-184" title="Green Archive" src="http://jblog.it/wp-content/uploads/2009/04/greenarchive.jpg" alt="Green Archive" width="270" height="180" /></a>Iniziamo una <strong>lunga serie di articoli sull&#8217;ottimizzazione dei siti web</strong> in cui verranno trattate le tecniche e i suggerimenti per rendere efficiente il proprio sito web.</p>
<p><span class="highlight_yellow"><strong>In questo articolo</strong> parlo della cache dei browser, come e perché gestirla. Vedrai cos&#8217;è una richiesta http, un&#8217;intestazione http e le tre tecniche principali per istruire il browser su come dovrà comportarsi con gli elementi di una pagina, cioé, quando leggerli dal server d&#8217;origine e quando caricarli dalla cache.</span><br />
<span id="more-124"></span></p>
<h2>Cos&#8217;è una richiesta http?</h2>
<p><!--adv300--></p>
<p>Quando il browser visita un sito apre una connessione con l&#8217;host (il server che ospita il sito), composta da una <strong>richiesta </strong>e da una <strong>risposta</strong>. Supponiamo di voler visitare la pagina http://jblog.it/informazioni.html.</p>
<h5>La richiesta http che invia il browser</h5>
<p><code><strong>GET /informazioni HTTP/1.1</strong><br />
<strong>Host:</strong> jblog.it<br />
<strong>User-Agent:</strong> Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.9.0.8) Gecko/2009032609 Firefox/3.0.8<br />
<strong>Accept:</strong> text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8<br />
<strong>Accept-Language:</strong> it<br />
<strong>Accept-Encoding:</strong> gzip,deflate<br />
<strong>Accept-Charset:</strong> ISO-8859-1,utf-8;q=0.7,*;q=0.7<br />
<strong>Keep-Alive: </strong>300<br />
<strong>Connection:</strong> keep-alive</code></p>
<h5>La risposta http</h5>
<p><code><strong>HTTP/1.1 200 OK</strong><br />
<strong>Date:</strong> Fri, 24 Apr 2009 10:26:08 GMT<br />
<strong>Server</strong>: Apache<br />
<strong>Keep-Alive:</strong> timeout=15, max=100<br />
<strong>Connection:</strong> Keep-Alive<br />
<strong>Transfer-Encoding:</strong> chunked<br />
<strong>Content-Type:</strong> text/html; charset=UTF-8</code></p>
<p>Le informazioni inviate e restituite potrebbero essere molte di più, ognuna ha un suo preciso significato, e possono essere controllate e gestite via codice (lato client e lato server). Sul sito del w3c puoi trovare l&#8217;elenco completo dei campi di intestazione delle connessioni http: <a rel="nofollow" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html">http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html</a>.</p>
<h5>La prima riga della richiesta: GET /informazioni HTTP/1.1</h5>
<p><strong> </strong>In questa riga si trovano sostanzialmente tre informazioni: il <strong>tipo della richiesta</strong> (GET, POST, HEAD, PUT, DELETE, OPTIONS, TRACE), l&#8217;<strong>indirizzo della risorsa</strong> (/informazioni) e il <strong>protocollo </strong>con cui si effettua la richiesta (HTTP/1.1).</p>
<h5>La prima riga della risposta: HTTP/1.1 200 OK</h5>
<p><strong> </strong>Il codice 200 indica il successo della risposta http. Esistono vari codici numerici per indicare l&#8217;esito della risposta http. Ad esempio, il classico <strong>codice 404</strong> indica che non è stata trovata la risorsa specificata nella richiesta http. Se ti interessa puoi trovare una <strong>lista completa</strong> su wikipedia: <a rel="nofollow" href="http://it.wikipedia.org/wiki/Elenco_dei_codici_di_stato_HTTP">http://it.wikipedia.org/wiki/Elenco_dei_codici_di_stato_HTTP</a>.</p>
<h3>Perché bisogna ridurre le richieste http?</h3>
<p>Il numero di richieste http dipende dal <strong>numero di elementi da caricare</strong>. Ad esempio, se in una pagina ci sono 2 immagini e 1 foglio di stile il browser effettuerà 4 richieste http (una è per il codice html della pagina).</p>
<p>Come avrai ben capito, la regola è &#8220;ridurre gli elementi della pagina&#8221;, o meglio &#8220;ottimizzare gli elementi di una pagina senza eliminarne nessuno&#8221;. Con &#8220;ottimizzare&#8221; non intendo &#8220;ridurre la loro dimensione&#8221;. Infatti riducendo la dimensione degli elementi avresti un miglior tempo di caricamento mantenendo lo stesso numero di richieste http.</p>
<h4>Ottimizzare o ridurre?</h4>
<p>Senza dubbio è importantissimo ottimizzare la qualità e le dimensioni dei componenti di una pagina, ma una singola richiesta http è molto più gravosa di qualche kbyte in più. Ecco perché <strong>ridurre le richieste http è fondamentale</strong>.</p>
<h2>I campi di intestazione del protocollo HTTP per gestire la cache</h2>
<p><span style="text-decoration: underline;"><a href="http://jblog.it/2009/04/24/ridurre-richieste-http-come-utilizzare-cache-browser_124.html"><img class="alignright size-full wp-image-185" title="Gift Tag" src="http://jblog.it/wp-content/uploads/2009/04/gifttag.jpg" alt="Gift Tag" width="267" height="200" /></a></span>Il protocollo HTTP 1.1 ha alcuni campi di intestazione (o header fields) che consentono di fornire alcune informazioni riguardo un file (data, ultima modifica, periodo, ecc.) e controllare la cache.</p>
<h4>Cache-Control</h4>
<p>Specifica le direttive che devono rispettare tutti i metodi di caching dei componenti restituiti. Le direttive di cache-control:</p>
<ol>
<li>sovrascrivono gli algoritmi di caching di default</li>
<li>non possono essere specificate per una singola cache (se si utilizza un proxy o un gateway)</li>
<li>sono unidirezionali, cioè non implicano che la risposta abbia le stesse direttive</li>
</ol>
<p>Alcune direttive possono essere utilizzate solo in fase di richiesta o solo in fase di risposta.</p>
<ul>
<li><strong>direttive di richiesta: </strong>no-cache, no-store, max-age, max-stale, min-fresh, no-transform, only-if-cached, cache-extension.</li>
<li><strong>direttive di risposta:</strong> public, private, no-cache, no-store, no-transform, must-revalidate, proxy-revalidate, max-age, s-maxage, cache-extension.</li>
</ul>
<p><strong>public.</strong> La risposta può essere memorizzata in qualsiasi cache. Utile se si utilizza una cache condivisa.</p>
<p><strong>private.</strong> La risposta non deve essere memorizzata nella cache condivisa.</p>
<p><strong>no-cache.</strong> Evita che la risposta venga memorizzata in cache. SOLO in fase di risposta è possibile scrivere <code>no-cache="field-name"</code>, dove <em>field-nam</em><em>e</em> è il nome di un campo di intestazione che non si vuole memorizzare in cache. In pratica, quando una risposta (ad es. una pagina) viene memorizzata in cache, vengono memorizzati anche i suoi campi di intestazione. Se uno di quei campi è &#8220;Set-Cookie&#8221; e non vogliamo che venga memorizzato in cache basterà scrivere <code>no-cache="Set-Cookie"</code>. In tal modo la pagina verrà comunque memorizzata in cache senza il campo di intestazione &#8220;Set-Cookie&#8221;. <strong>L&#8217;utilità?</strong> Dato che &#8220;Set-Cookie&#8221; crea un cookie, memorizzandolo con la pagina, quando si riutilizzerà la versione in cache verrà creato nuovamente il cookie.</p>
<p><strong>no-store.</strong> Evita che la risposta venga memorizzata permanentemente nella memoria non-volatile. Questa direttiva si applica a qualsiasi tipo di cache (condivisa e non). La sua utilità consiste nel fatto che si impedisce la memorizzazione di vecchie versioni di pagine e documenti che vengono costantemente aggiornati.</p>
<p><strong>s-maxage. </strong>Specifica il periodo (in secondi) dopo il quale devono essere aggiornate le risposte nella <strong>cache condivisa.</strong> Questa direttiva sovrascrive la direttiva <em>max-age </em>e il campo di intestazione <em>expires</em>.</p>
<p><strong>max-age.</strong> Indica che il client è disposto ad accettare una risposta con un periodo (in secondi) maggiore di quello specificato. Se non è specificata la direttiva <em>max-stale</em>, il client non accetterà una risposta datata.</p>
<p><strong>min-fresh.</strong> Indica che il client è disposto ad accettare una risposta che sia aggiornata <em>almeno</em> a un dato periodo (in secondi).</p>
<p><strong>max-stale.</strong> Indica che il client è disposto ad accettare una risposta che supera la sua scadenza di un certo numero di secondi.</p>
<p><strong>only-if-cached.</strong> Consente di caricare un contenuto solo se in cache è presente una sua versione, altrimenti non viene restituita alcuna risposta. Questa direttiva è utile nelle reti particolarmente lente.</p>
<p><strong>must-revalidate. </strong>Poichè una cache può essere configurata in modo che ignori il tempo di scadenza di una risposta, questa direttiva consente di forzare l&#8217;aggiornamento di una risposta già memorizzata in cache. Questa direttiva viene sempre rispettata dal browser.</p>
<p><strong>proxy-revalidate.</strong> Ha gli stessi effetti di must-revalidate, ma solo sulla cache condivisa.</p>
<p><strong>no-transform.</strong> Evita che una cache intermedia (ad es. di un proxy) manipoli la risposta per risparmiare risorse. Infatti può succedere che un proxy comprima un&#8217;immagine per risparmiare spazio. Questa direttiva è utile nel caso di immagini da trasmettere fedelmente (ad es. in campo medico) in cui ogni pixel deve rimanere al suo posto.</p>
<h4>Expires</h4>
<p>Indica una data (con l&#8217;ora) a partire dalla quale la risposta memorizzata in cache deve essere considerata &#8220;vecchia&#8221;, quindi essere aggiornata.</p>
<p>La data deve essere espressa in un preciso formato definito dal protocollo HTTP. Ad esempio: <code>Tue, 03 Nov 2007 17:30:00 GMT.</code></p>
<p><code>Expires: Tue, 03 Nov 2007 17:30:00 GMT</code></p>
<h4>Pragma</h4>
<p>Indica che la risposta non deve essere memorizzata in cache. L&#8217;unica direttiva è appunto &#8220;no-cache&#8221;.</p>
<p>In pratica esegue la stessa funzione di cache-control=&#8221;no-cache&#8221;, ma è necessario utilizzarla per mantenere la compatibilità con la versione 1.0 del protocollo HTTP.</p>
<p><code>Pragma: no-cache</code></p>
<h4>ETag</h4>
<p>Gli ETag o <strong>Entity Tag</strong> rappresentano un modo semplice ed efficiente per determinare se la risposta nella cache corrisponde a quella che si trova nel server di origine. Concretamente un ETag non è altro che una <strong>stringa che identifica univocamente una risposta memorizzata in cache</strong>.</p>
<p><strong>Com&#8217;è composta la stringa?</strong> Non ha dei valori predefiniti ma deve essere creata in base a dei valori che potrebbero identificare la versione di una risposta. Generalmente si preferisce identificare le risposte in base alla data dell&#8217;ultima modifica e alla dimensione. Queste due informazioni vengono compresse in modo da formare un&#8217;unica stringa di dimensioni contenute, ad esempio utilizzando algoritmi di hashing come md5.</p>
<p><strong>Gli svantaggi.</strong> L&#8217;unico svantaggio è che il formato e il valore di un ETag cambia da server a server. Se un determinato file risiede su più server nella stessa directory, con identiche dimensioni, permessi, timestamp, a seconda del server da cui si legge. La <strong>soluzione </strong>consiste nel creare il valore dell&#8217;ETag con un semplice script lato-server. In pratica, per <strong>avere dei benefici</strong> dagli ETag è necessario gestirli completamente con degli script lato-server, altrimenti è meglio non utilizzarli. <a href="#script1">Ecco un esempio di script</a>.</p>
<p><code>ETag: "0401g4ff812fgk12gqg2g4j7"</code></p>
<h4>Last-Modified</h4>
<p>Rappresenta la data e l&#8217;ora dell&#8217;ultima modifica del file sul server d&#8217;origine nella forma, ad esempio, <code>Tue, 03 Nov 2007 17:30:00 GMT.</code></p>
<p>Questo campo di intestazione è utile soprattutto nelle pagine dinamiche in cui vengono stampati dei dati ricavati da un database, o nei file creati dinamicamente (ad es. un foglio di stile che ne unisce 5 per evitare di avere 5 richieste http).</p>
<h4>If-Match</h4>
<p>Fornisce un metodo efficiente per controllare se la risposta ottenuta corrisponde a quella memorizzata in cache, utilizzando gli <strong>ETag</strong>, ed eventualmente aggiornarla. Viene anche usata per evitare <strong>modifiche accidentali</strong> sull&#8217;errata versione di una risorsa.</p>
<p><code>If-Match:*</code> oppure <code>If-Match:0401g4ff812fgk12gqg2g4j7</code></p>
<p>Nel primo caso, il carattere &#8220;*&#8221; è un carattere speciale e il campo fa corrispondere tutti i componenti di una risposta.</p>
<p>Nel secondo caso, il campo di intestazione fa corrispondere l&#8217;ETag con la stringa specificata.</p>
<h4>If-None-Match</h4>
<p>Fornisce un metodo efficiente per controllare se la risposta ottenuta corrisponde a quella memorizzata in cache, utilizzando gli <strong>ETag</strong>, ed eventualmente aggiornarla.</p>
<p>Al contrario di If-Match non si deve avere la corrispondenza con l&#8217;ETag confrontato o con il carattere &#8220;*&#8221;.</p>
<p><code>If-None-Match:*</code> oppure <code>If-Match:0401g4ff812fgk12gqg2g4j7</code></p>
<h4>If-Modified-Since</h4>
<p>Fornisce un metodo automatico per aggiornare la versione in cache di una risposta che non è stata modificata da una certa data (e ora) nel formato: <code>Tue, 03 Nov 2007 17:30:00 GMT. Se la risposta è stata modificata a partire dalla data specificata si effettua l'aggiornamento della versione in cache, altrimenti viene restituita la versione memorizzata in cache.</code></p>
<p><code>If-Modified-Since: Sat, 12 Oct 2008 20:12:00 GMT</code></p>
<h4>If-Unmodified-Since</h4>
<p>Fornisce un metodo automatico per aggiornare la versione in cache di una risposta che non è stata modificata da una certa data (e ora) nel formato: <code>Tue, 03 Nov 2007 17:30:00 GMT. Se la risposta NON è stata modificata a partire dalla data specificata si effettua l'aggiornamento della versione in cache, altrimenti viene restituita la versione memorizzata in cache.</code></p>
<p><code>If-Unmodified-Since: Sat, 12 Oct 2008 20:12:00 GMT</code></p>
<h4>If-Range</h4>
<p>Se la versione in cache di una risposta è parziale, questo campo di intestazione permette di ottenere solo la parte mancante. La condizione fallisce se la risorsa richiesta è stata modificata. In questo caso sarà effettuata una seconda richiesta per ottenere una risposta completa che aggiorni la versione memorizzata in cache.</p>
<p><code>If-Range: Sat, 12 Oct 2008 20:12:00 GMT</code></p>
<p><code>If-Range: 0401g4ff812fgk12gqg2g4j7</code></p>
<p>Nel primo caso si confronta la data dell&#8217;<strong>ultima modifica</strong>, mentre nel secondo caso si confronta la stringa dell&#8217;<strong>ETag</strong>.</p>
<h2>Come utilizzare i campi di intestazione</h2>
<p><span style="text-decoration: underline;"><a href="http://jblog.it/2009/04/24/ridurre-richieste-http-come-utilizzare-cache-browser_124.html"><img class="alignright size-full wp-image-186" title="Thinking" src="http://jblog.it/wp-content/uploads/2009/04/thinking.jpg" alt="Thinking" width="267" height="171" /></a></span>In questo paragrafo non troverai una ricetta pronta per gestire la cache perché non so quali sono le tue esigenze. Leggi attentamente il paragrafo precedente per decidere le operazioni da effettuare in ogni pagina e risorsa del tuo sito.</p>
<p><strong>Il mio consiglio</strong> è quello di analizzare i contenuti delle tue pagine (attuali e futuri) e decidere se memorizzare in cache una particolare risorsa, come gestire la versione della cache, il tempo di validità, ecc.</p>
<p>Se nel paragrafo precedente alcuni punti sono spiegati male, manca qualcosa o ci sono errori  fammelo sapere e correggerò tutto al più presto.</p>
<p>Ci sono <strong>tre metodi</strong> per impostare i campi di intestazione:</p>
<ol>
<li>impostando il tag &lt;meta&gt;</li>
<li>all&#8217;interno del proprio codice lato-server (php, asp, cgi, ecc.)</li>
<li>configurando il web server Apache tramite il file .htaccess o il file principale httpd.conf</li>
</ol>
<h3>1. Impostare i tag &lt;meta&gt;</h3>
<p>Sicuramente conoscerai già il tag &lt;meta&gt;. Probabilmente l&#8217;avrai utilizzato per inserire <strong>description</strong> e <strong>keywords</strong> nelle tue pagine web, per migliorare l&#8217;indicizzazione del tuo sito da parte dei motori di ricerca.</p>
<p>Per ogni campo di intestazione che decidi di utilizzare devi:</p>
<ul>
<li>creare un tag &lt;meta&gt; con gli attributi &#8220;http-equiv&#8221; e &#8220;content&#8221;</li>
<li>scrivere il nome del campo nell&#8217;attributo &#8221;http-equiv&#8221;, rispettando le lettere maiuscole e minuscole</li>
<li>scrivere il valore del campo nell&#8217;attributo &#8220;content&#8221;</li>
</ul>
<h5>Esempi</h5>
<p><code>&lt;meta http-equiv="Cache-Control" content="no-cache" /&gt;<br />
&lt;meta http-equiv="Pragma" content="no-cache" /&gt;<br />
&lt;meta http-equiv="Expires" content="Tue, 03 Nov 2007 17:30:00 GMT" /&gt;</code></p>
<h3>2. Il codice lato-server</h3>
<p>Ogni linguaggio di programmazione ha la sua funzione per inviare un campo di intestazione.</p>
<p>Al momento l&#8217;unico linguaggio che conosco è PHP, con cui basterà scrivere <code>header("Cache-Control: no-cache");</code> .</p>
<p>I campi di intestazione vanno scritti prima di qualsiasi output sulla pagina, altrimenti si verifica un errore che in sostanza dice &#8220;impossibile modificare l&#8217;intestazione &#8211; gli header sono stati già inviati&#8221;.</p>
<p><strong>Tutto qui?</strong> <span style="font-weight: normal;">In teoria non ci sarebbe altro&#8230; Posso solo aggiungere delle situazioni in cui diventa fondamentale utilizzare la funzione <em>header</em>.</span></p>
<h5>Combinare più fogli di stile</h5>
<p>Per diminuire le richieste http è una buona abitudine combinare più fogli di stile in uno solo. Si potrebbe fare manualmente, ma se in futuro vorrai effettuare delle modifiche dovrai modificare i singoli file e ricombinarli oppure modificare il file grande con la difficoltà di aver a che fare con centinaia di righe di codice.</p>
<p>Il metodo è quello di creare un file .css in cui inserire uno <strong>script php</strong> che permetta di stampare al suo interno tutti i file .css da te specificati. Dovrai inoltre impostare Apache affinché processi i file .css come file .php .</p>
<p>Per file dinamici di questo tipo sarà necessario richiamare più volte la funzione <em>header </em>all&#8217;inizio del file in modo da <strong>inviare i campi di intestazione</strong> riguardanti la gestione della cache.</p>
<p>Questo argomento farà parte del prossimo articolo su come combinare e ottimizzare immagini, css e script.</p>
<p><span id="script1">Ecco un <strong><em>semplice script php</em></strong>.</span></p>
<pre lang="php">&lt; ?
$files = array("css1.css","css2.css");
$mtime = 0;
$this_mtime = 0;
ob_start();
foreach($files as $file)
{
	if(file_exists($file))
	{
		include($file); /* includo il file */
		$this_mtime = filemtime($file); /* leggo la data dell'ultima modifica */
		if($mtime &lt; $this_mtime) $mtime=$this_mtime;
	}
}
$lenght = ob_get_length(); /* lunghezza del contenuto */
$content = ob_get_contents(); /* il contenuto nella variabile $content da stampare successivamente */ ob_end_clean();

/* Headers */
header("Content-Type: text/css");
header("Last-Modified: ".date("D, d M Y H:i:s",$mtime)." GMT");
header("Content-Length",$lenght);
header("ETag: ".md5("compressed.css".$lenght.$mtime)); /* il file si chiama compressed.css */
header("Cache-Control: max-age=345600");

/* Stampo il contenuto */
echo $content;
?&gt;</pre>
<ul>
<li>per calcolare l&#8217;ultima modifica da inviare nel campo di intestazione &#8220;Last-Modified&#8221; sarà quella del file che è stato modificato più recentemente</li>
<li>nell&#8217;ETag inserisco anche il nome del file per aumentare l&#8217;univocità dell&#8217;ETag</li>
</ul>
<p>Come ultima operazione inserire nel file .htaccess la riga:</p>
<p><code>AddHandler application/x-httpd-php .css</code></p>
<p>Questa riga fa in modo che Apache processi i file css come file php.</p>
<h5>Pagine dinamiche e database</h5>
<p>Quando una pagina &#8220;dinamica&#8221; ha sempre gli <strong>stessi dati per diversi giorni</strong> è importante fare in modo che un utente, a partire dalla seconda visita, non ricarichi una nuova versione di quella pagina ma legga la versione memorizzata in cache.</p>
<p>Nei cms, come in Wordpress, c&#8217;è una netta separazione fra template e codice. In alcuni non è possibile creare un template per una singola pagina per altri, come Wordpress, si. Tuttavia, secondo me, è totalmente inutile creare un template per scrivere solo i tag &lt;meta&gt; e avere una gestione personalizzata della cache per quella pagina. Per questo motivo conviene <strong>inviare i campi di intestazione all&#8217;interno del codice</strong>.</p>
<p>Una prima idea è quella di definire delle condizioni per cui dei record restituiti dal database devono essere considerati &#8220;vecchi&#8221;, e in base a queste ed altre condizioni inviare gli opportuni valori dei campi di intestazione.</p>
<h3>3. Configurare il web server Apache</h3>
<p><a href="http://jblog.it/2009/04/24/ridurre-richieste-http-come-utilizzare-cache-browser_124.html"><img class="alignright size-full wp-image-181" title="Apache Server" src="http://jblog.it/wp-content/uploads/2009/04/4229-apache-server.jpg" alt="Apache Server" width="172" height="83" /></a>Per gestire la cache con Apache è necessario caricare i moduli <strong>mod_expires</strong> e <strong>mod_headers</strong>.</p>
<h5>Caricare i moduli</h5>
<ul>
<li>cerca e apri il file <strong>httpd.conf</strong></li>
<li>individua la lunga lista di &#8220;mod_&#8230;&#8221;</li>
<li>individua le righe con &#8220;mod_expires&#8221; e &#8220;mod_header&#8221;</li>
<li>elimina (se c&#8217;è) il carattere &#8220;#&#8221; che si trova prima del nome dei moduli che vuoi attivare</li>
<li>riavvia il server Apache</li>
</ul>
<p>A questo punto, nel file <strong>.htaccess</strong> bisogna definire le regole che consentono di gestire la cache a seconda del tipo o estensione dei file richiesti durante le connessioni http.</p>
<h5>Il modulo mod_expires</h5>
<p>Per conoscere meglio questo modulo ti consiglio di andare a leggere la guida ufficiale di Apache (in inglese): <a rel="nofollow" href="http://httpd.apache.org/docs/2.2/mod/mod_expires.html">http://httpd.apache.org/docs/2.2/mod/mod_expires.html</a>.</p>
<h5>Il modulo mod_headers</h5>
<p>Per conoscere meglio questo modulo ti consiglio di andare a leggere la guida ufficiale di Apache (in inglese): <a rel="nofollow" href="http://httpd.apache.org/docs/2.2/mod/mod_headers.html">http://httpd.apache.org/docs/2.2/mod/mod_headers.html</a>.</p>
<h5>Gestione della cache in base all&#8217;estensione</h5>
<pre>ExpiresActive On
ExpiresDefault A300
&lt;FilesMatch ".html$"&gt;
	Expires A86400
&lt;/FilesMatch&gt;
&lt;FilesMatch ".(gif|jpg|png|js|css)$"&gt;
	Expires A2592000
&lt;/FilesMatch&gt;</pre>
<ul>
<li>la prima riga (<strong>ExpiresActive</strong>) attiva il modulo &#8220;mod_expires&#8221;</li>
<li>la seconda riga (<strong>ExpiresDefault</strong>) imposta un valore di default del campo di intestazione &#8220;Expires&#8221; pari a 300 secondi</li>
<li>il primo blocco &lt;FilesMatch&gt; fa in modo che tutti i file html abbiano il campo di intestazione &#8220;Expires&#8221; con il valore 86400 secondi</li>
<li>il secondo blocco &lt;FilesMatch&gt; fa in modo che tutti i file gif, jpg, png, js, css abbiano il campo di intestazione &#8220;Expires&#8221; con il valore 2592000 secondi</li>
<li>la lettera <strong>A</strong> indica che il valore viene impostato <strong>dopo l&#8217;accesso</strong> al file, mentre la lettera <strong>M</strong> imposterebbe il valore <strong>dopo la modifica</strong> al file</li>
</ul>
<p><strong>Svantaggi.</strong> Spesso capita che alcuni file, benché siano dello stesso tipo, abbiano estensioni diverse. Ad esempio, le immagini con una compressione Jpeg possono avere l&#8217;estensione jpg oppure jpeg. Quindi se capitasse un file jpeg non si avrebbe la corrispondenza.</p>
<h5>Gestione della cache in base al tipo MIME</h5>
<p>Per assicurarci di individuare tutti i file di un certo tipo è necessario leggere il loro tipo MIME.</p>
<pre>ExpiresActive On
ExpiresDefault A300
ExpiresByType text/css "access plus 1 day"
ExpiresByType text/javascript "access plus 3 days"
ExpiresByType image/png "access plus 2 months"</pre>
<h2>Forzare l&#8217;aggiornamento dei componenti</h2>
<p>Se si utilizzano dei componenti che devono essere sempre aggiornati spesso non basta scrivere i campi di intestazione <code>"Cache-Control: no-cache"</code> e <code>"Pragma: no-cache"</code>. Esistono infatti <strong>prove documentate</strong> sul fatto che a volte questi campi vengono <strong>ignorati dai browser</strong>.</p>
<p>Quando utilizzavo un <strong>script captcha</strong> notavo che non si aggiornava l&#8217;immagine, il che era davvero un problema in quanto se l&#8217;utente sbagliava il codice doveva ricaricarsi la pagina con una nuova immagine.</p>
<p>La <strong>soluzione</strong> consiste nello scrivere l&#8217;indirizzo dell&#8217;immagine con un elemento dipendente dal tempo. Quindi, invece di scrivere:<br />
<code>&lt;img src="myimage.jpg" alt="La mia immagine" /&gt;</code></p>
<p>si cambierà l&#8217;indirizzo in:<br />
<code>&lt;img src="myimage.jpg?&lt;? echo time(); ?&gt;" alt="La mia immagine" /&gt;</code><br />
dove la funzione <code>time()</code> restituisce data e ora attuali in numeri interi (ad es. 11022103710).</p>
<p>Nel caso si utilizzi l&#8217;<strong>immagine come sfondo</strong>, anziché scrivere:<br />
<code>&lt;div style="background:#000 url('img/blackback.png') no-repeat left bottom"&gt;&lt;/div&gt;</code></p>
<p>si dovrà modificare l&#8217;indirizzo in:<br />
<code>&lt;div style="background:#000 url('img/blackback.png?&lt;? echo time(); ?&gt;') no-repeat left bottom"&gt;&lt;/div&gt;</code></p>
<p>Uno dei <strong>possibili svantaggi</strong> sta nel fatto che non tutti i file possono essere processati con il compilatore php. Se vuoi che un file .js (javascript) o .css (foglio di stile) venga processato come un file php basterà aggiungere al file .htaccess le seguenti righe:</p>
<p><code>AddHandler application/x-httpd-php .css<br />
AddHandler application/x-httpd-php .js</code></p>
<p>Per concludere, scrivendo questo articolo ho scoperto un mondo riguardo la cache e la sua gestione, ed ho capito che gestire adeguatamente la cache permette di ottimizzare notevolmente il caricamento delle pagine di un sito web.</p>
<p>Come utilizzavi la cache fino ad oggi? Ti limitavi a scrivere i tre tag &lt;meta&gt; o avevi già pensato di iniziare a utilizzare la cache più seriamente? Ti sembra importante o è solo una mia impressione? L&#8217;articolo è scritto bene o manca qualcosa?</p>
<h6 class="highlight_red">Non perdere il prossimo articolo: &#8220;Ridurre le richieste HTTP (parte 2): combinare e ottimizzare immagini, script e css&#8221;.</h6>
<h4>Crediti</h4>
<ul>
<li><strong>Libro.</strong> Creare siti web ad alte prestazioni: <a rel="nofollow" href="http://www.tecnichenuove.com/libri/creare_siti_web_ad_alte_prestazioni.html" target="_blank">http://www.tecnichenuove.com/libri/creare_siti&#8230;</a></li>
<li>Guida ufficiale di Apache: <a rel="nofollow" href="http://httpd.apache.org/docs/2.2/" target="_blank">http://httpd.apache.org/docs/2.2/</a></li>
<li>Use Server Cache Control to Improve Performance: <a rel="nofollow" href="http://websiteoptimization.com/speed/tweak/cache/" target="_blank">http://websiteoptimization.com/speed/tweak/cache/</a></li>
<li>Foto1: <a rel="nofollow" href="http://www.flickr.com/photos/aureusbay/297387489/">http://www.flickr.com/photos/aureusbay/297387489/</a></li>
<li>Foto2: <a href="http://www.flickr.com/photos/thingsarebetterwithaparrott/1054908626/">http://www.flickr.com/photos/thingsarebetterwithaparrott/1054908626/</a></li>
<li>Foto3: <a rel="nofollow" href="http://www.flickr.com/photos/galopoulos/567890941/">http://www.flickr.com/photos/galopoulos/567890941/</a></li>
</ul>
<img src="http://jblog.it/?ak_action=api_record_view&id=124&type=feed" alt=" Ridurre le richieste HTTP (parte 1): come utilizzare la cache del browser"  title="Ridurre le richieste HTTP (parte 1): come utilizzare la cache del browser" />]]></content:encoded>
			<wfw:commentRss>http://jblog.it/2009/04/24/ridurre-richieste-http-come-utilizzare-cache-browser_124.html/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
	</channel>
</rss>
