Per default ogni pagina pubblicata da Apache viene annunciata come charset ISO-8859-1 (direttiva AddDefaultCharset on). Per servire delle specifiche pagine in altro set di caratteri (esempio cirillico con il set WINDOWS-1251 o cinese semplificato con il set GB2312), si aggiungono le seguenti direttive nel file di configurazione di Apache:
<Directory /home/vill-ftp/www/>
AddLanguage ru .ru
AddLanguage zh .zh
AddCharset WINDOWS-1251 .cp-1251 .win-1251
AddCharset GB2312 .gb2312 .gb
</Directory>
Questo significa che rinominando i file .html con il suffisso .win-1251 oppure .gb2312 si forza il relativo set di caratteri. Con la doppia estensione si imposta lingua e set di caratteri; ad esempio index.html.zh.gb verrà annunciato come un file in lingua cinese e set di caratteri cinese semplificato.
Per i file PHP si possono aggiungere degli header in questo modo:
header("Content-Type: text/html; charset=gb2312"); header("Content-Language: zh");
oppure
header("Content-Type: text/html; charset=windows-1251"); header("Content-Language: ru");
Per impostare il charset di default su Apache2 si mette la seguente riga dentro la sezione relativa al VirtualHost:
AddDefaultCharset utf-8
La direttiva può altrimenti essere specificata solo per una sezione <Directory>. Ovviamente si devono creare pagine in codifica UTF-8.
Bisogna stare attenti alla funzione htmlentities() del PHP, ad esempio la seguente sequenza di byte esadecimali <E2><80><99> rappresenta l'apostrofo rovesciato (backtik) in UTF-8, ma data in pasto ad htmlentities() viene convertita in â<80><99>.
Per fortuna la funzione htmlentities() accetta un terzo parametro, il charset. Purtroppo non si trova una combinazione per far funzionare tutto e sempre. Ad esempio htmlentities(UTF-8) non converte la o-umlaut in modo adatto all'Apache con DefaultCharset UTF-8:
| Codifica | Intenzione | htmlentities(ISO-8859-1) | htmlentities(UTF-8) | Buono per Apache UTF-8 |
|---|---|---|---|---|
| <E2><80><99> | apostrofo | â<80><99> | ’ | <E2><80><99> |
| <F6> | o-umlaut | ö | <F6> | ö |
NOTA E' sbagliato codificare la o-umlaut in <F6>, quella sarebbe la codifica in Unicode puro, non la codifica UTF-8 che è invece <C3><B6>! Vedere codifica UTF-8 su http://www1.tip.nl/~t876506/utf8tbl.html.
NOTA Per convertire in/da UTF-8 in Perl vedere http://userpage.fu-berlin.de/~ram/pub/pub_jf47hxhHHt/perl_unicode_en.
Per la codifica UTF-8 in PHP si suggerisce:
echo htmlentities($string, ENT_COMPAT, 'UTF-8');
Come specificare alcune opzioni valide per il modulo mod_autoindex. In una sezione Directory o VirtualHost, oppure al top level del file di configurazione di Apache:
# Allow more room for file names in auto indexes.
<IfModule mod_autoindex.c>
IndexOptions NameWidth=45
</IfModule>
Supportata da quasi tutti i browser, però la password transita in chiaro sulla rete (a meno che non si stia usando https). Nella directory da proteggere si mette un file di nome .htaccess con qualcosa del tipo:
AuthType Basic AuthName "Area protetta" AuthUserFile /etc/apache2/htpasswd Require valid-user
Il file con le password va indicato con percorso assoluto oppure relativo alla directory di configurazione di Apache. Per gestire le password si usa il comando htpasswd, possibilmente con l'opzione -m. Il file .htpasswd può essere messo anche direttamente nella directory da proteggere, leggibile ad Apache ma possibilmente non a tutti gli altri:
-rw-r--r-- 1 root root 143 Feb 23 12:02 .htaccess -rw-r----- 1 root www-data 50 Feb 23 12:00 .htpasswd
A livello di configurazione generale, verificare che l'accesso ai file .ht sia inibito e che la directory da proteggere abbia il giusto AllowOverride:
<Files ~ "^\.ht">
Order allow,deny
Deny from all
</Files>
<Directory /path/to/directory/>
AllowOverride AuthConfig Limit
</Directory>
Rispetto all'autenticazione base c'è una maggiore sicurezza in quanto la password non transita in chiaro sulla rete, viene trasmesso un digest della password invece del clear text. Per attivare l'autenticazione di tipo Digest su una directory si aggiunge questa sezione al file di configurazione di Apache:
<Directory /var/www/niccolo/>
BrowserMatch "MSIE" AuthDigestEnableQueryStringHack=On
AllowOverride AuthConfig
</Directory>
Notare l'hack che Apache deve fare in modo che l'autenticazione Digest funzioni anche con il difetto di Internet Explorer. Nella directory da proteggere si salva questo file .htaccess e il relativo file .htpasswd:
Per Apache 2.2
# Per aggiungere un utente al file delle password: # htdigest [-c] .htpasswd realm_name user1 AuthType Digest AuthName "private area" AuthDigestDomain /private/ http://mirror.my.dom/private/ AuthDigestProvider file AuthUserFile /var/www/niccolo/.htpasswd Require valid-user
Per Apache 2.0 e precedenti
# Per aggiungere un utente al file delle password: # htdigest [-c] .htpasswd realm_name user1 AuthType Digest AuthName "private area" AuthDigestFile /var/www/niccolo/.htpasswd Require user user1 user2
Il file con le password si gestisce con htdigest e contiene righe del tipo:
username:realm:0762ba1444823379febd9e3f9eb7c0aa
Per Debian 4.0 (Sarge) non c'è il pacchetto libapache2-mod-auth-mysql, per fortuna si riesce ad installare quello per Debian Testing, almeno per ora. Giusto per sicurezza lo salvo anche qui: libapache2-mod-auth-mysql_4.3.9-3_i386.deb.
Nella configurazione globale di Apache ci vuole:
#-------------------------------------------------------------------------- # MySQL authentication: default access to the database. #-------------------------------------------------------------------------- AuthMySQL_DefaultHost localhost AuthMySQL_DefaultUser guest AuthMySQL_DefaultPassword guest AuthMySQL_AllowOverride On
Poi nella directory da proteggere si crea il file .htaccess con:
AuthName "Accesso riservato" AuthType Basic AuthBasicAuthoritative Off Auth_MYSQL on AuthMySQL_Host localhost AuthMySQL_User username AuthMySQL_Password secret Auth_MySQL_DB dbname Auth_MySQL_Password_Table user_auth Auth_MySQL_Username_Field user_name Auth_MySQL_Password_Field user_passwd Auth_MySQL_Encrypted_Passwords Off Auth_MySQL_Scrambled_Passwords Off Auth_MySQL_Empty_Passwords Off Auth_MySQL_Group_Table user_group Auth_MySQL_Group_Field user_group require valid-user
Importante è la direttiva AuthBasicAuthoritative Off, che non si trova documentata (forse non serviva con Apache 2.0?). In pratica senza questa direttiva viene comunque tentata l'autenticazione su file che fallisce e quindi quella su MySQL non viene neanche provata.
Per autenticare gli utenti su /etc/passwd e /etc/shadow si potrebbe usare il modulo Apache di autenticazione PAM, però sarebbe necessario che apache avesse i permessi di lettura su /etc/shadow, il che non è il massimo del godimento.
Per fortuna esiste il modulo Apache mod-auth-shadow, che deve essere espressamente compilato per Apache oppure per Apache2.
In Debian il pacchetto ha subito varie vicissitudini, entrando ed uscendo dalla distribuzione ufficiale. Il risultato purtroppo è che non esiste per Apache2 né in Etch né in Lenny. Per forunta è facile ricompilarlo dai sorgenti Debian o Ubuntu.
Qui trovate un backport per Etch della versione 2.1, qui invece la versione per Lenny.
Il file di configurazione di Apache deve essere qualcosa di simile:
<Directory /var/www/admin/>
AuthType Basic
AuthName "Area riservata di amministrazione"
AuthShadow on
# AuthAuthoritative for Apache 2.0
# AuthBasicAuthoritative for Apache 2.2
AuthBasicAuthoritative Off
AuthUserFile /dev/null
Require user niccolo angela
</Directory>
Attenzione, la direttiva AuthUserFile /dev/null serve perché Apache comunque tenta l'autenticazione Basic (sebbene non autoritativa) aprendo un file password, se non lo specifichiamo si ottengono continui messaggi di errore nel log di Apache:
[Fri Sep 07 16:14:46 2007] [error] Internal error: pcfg_openfile() called with NULL filename
Per consentire l'accesso ad una directory solo a determinati indirizzi IP:
<Directory /var/www/private_dir>
Order deny,allow
Deny from all
Allow from 88.57.16.27 87.241.56.133
</Directory>
La notazione supportata da Allow è molteplice:
| Allow from .net example.edu | A (partial) domain-name |
|---|---|
| Allow from 192.168.1.104 192.168.1.205 | Full IP address |
| Allow from 10 172.20 192.168.2 | Partial IP address |
| Allow from 10.1.0.0/255.255.0.0 | Network/netmask pair |
| Allow from 10.1.0.0/16 | Network/nnn CIDR specification |
In un sito pubblico conviene nascondere gli errori PHP (non farli vedere nella pagina web), ma piuttosto loggarli in un file apposito, questa non è la configurazione predefinita Debian Lenny. Per attivare questo:
mkdir /var/log/php touch /var/log/php/error.log chown www-data:adm /var/log/php/error.log chmod 640 /var/log/php/error.log
mentre nel file /etc/php5/apache2/php.ini ci deve essere:
display_errors = Off log_errors = On error_log = /var/log/php/error.log
Ricordarsi di ruotare il file di log con un opportuno /etc/logrotate.d/.
Per un sito in fase di sviluppo è comodo visualizzare gli errori direttamente nella pagina web, se questo è disabilitato a livello globale, è possibile abilitarlo localmente con delle direttive in un file .htaccess:
php_flag display_errors on php_flag display_startup_errors on # See http://www.php.net/manual/en/errorfunc.constants.php # 1 E_ERROR # 2 E_WARNING # ... # 32767 E_ALL php_value error_reporting 32767
Le direttive <Directory> e <Location> si assomigliano molto, la differenza sostanziale è che Directory è intesa per lavorare a livello di filesystem, mentre Location è intesa a livello di URL.
Esempio di rewrite da impostare in un file .htaccess per ridirigere tutte le richieste example.com verso www.example.com o viceversa:
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^/(.*)$ http://www.example.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^/(.*)$ http://example.com/$1 [L,R=301]
Il flag [NC] significa no case sensitive, il flag [L] significa last rule (non se ne applicano altre), il flag [R] indica di effettuare un redirect con status code 301 Moved Permanently.
Per vedere quali regole di rewrite vengono appicalte si abilita temporaneamente nella sezione VirtualHost:
RewriteLog "/tmp/rewrite.log" RewriteLogLevel 2
Per creare una chiave RSA e il certificato autofirmato si crea un file di configurazione /etc/apache2/ssl/www.rigacci.org.cnf:
#---------------------------------------------------------------- # Create an RSA key and a self-signed Certificate with the # following command: # # openssl req -config /etc/apache2/ssl/file.cnf \ # -new -x509 -days 1095 -nodes \ # -keyout /etc/apache2/ssl/file.pem \ # -out /etc/apache2/ssl/file.pem # # The resulting file (unencrypted otherwise Apache can't start # automatically) will contains the RSA private key, so be sure # to set its mode to 0400. #---------------------------------------------------------------- [ req ] prompt = no default_bits = 1024 distinguished_name = www.rigacci.org_distinguished_name [ www.rigacci.org_distinguished_name ] countryName = IT stateOrProvinceName = Italy localityName = Firenze organizationName = Niccolo Rigacci organizationalUnitName = computer consultant commonName = www.rigacci.org emailAddress = webmaster@rigacci.org
Poi si esegue il comando openssl come scritto nel commento sopra. Invece nel file di configurazione di Apache (in default o in qualche VirtualHost) si mette:
SSLCertificateFile ssl/www.rigacci.org.pem