Websiteentwicklung: PHP: Konfiguration
Aus Wikibooks
Inhaltsverzeichnis |
[Bearbeiten] Grundlegendes
Nehmen Sie sich die Zeit PHP sorgfältig zu konfigurieren! Da PHP eine sehr mächtige Skriptsprache ist, die sehr viele Dinge kann, kann sie – (z. B.) falsch Konfiguriert – auch sehr viel kaputtmachen. Das soll Sie nur warnen und nicht gleich verschrecken ;)
Die Konfiguration PHPs wird über Direktiven gesteuert. Diese lassen sich in drei Gruppen einteilen, die durch die Konstanten PHP_INI_ALL, PHP_INI_PERDIR und PHP_INI_SYSTEM des Sourcen-Codes bestimmt werden.
- Erläuterung der Konstanten
- PHP_INI_ALL
- Ist eine PHP-Direktive mit dieser Konstante implementiert worden, kann sie in Scripten (z. B. durch ini_set()), in der php.ini und den Konfigurationsdateien httpd.conf und .htaccess geändert werden.
- PHP_INI_PERDIR
- Ist eine PHP-Direktive mit dieser Konstante implementiert worden, kann sie nicht in Scripten geändert werden, sondern nur in der php.ini und den Konfigurationsdateien httpd.conf und .htaccess.
- PHP_INI_SYSTEM
- Ist eine PHP-Direktive mit dieser Konstante implementiert worden, kann sie ausschließlich in der php.ini und der httpd.conf geändert werden.
[Bearbeiten] Die Konfigurationsdatei php.ini
Die php.ini ist die zentrale Konfigurationsdatei durch die alle Verhaltensregeln PHPs festgelegt werden. Innerhalb der Sourcen werden zwei verschiedene Konfigurationsdateien mitgeliefert. Das ist zum einen die php.ini-dist und zum anderen die php.ini-recommended. Sie sind gut kommentiert - allerdings nur für jemanden der sich bereits auskennt. Daher sollten sie dieses Kapitel gründlich lesen, damit auch Sie sich auskennen werden.
Manche Einstellung, die Sie in der php.ini vornehmen können, kann Ihnen Arbeit beim Programmieren abnehmen. Sie sollten sich also immer vergewissern, ob es für ein Problem, welches Sie beim Programmieren feststellen und lösen wollen, nur eines einfachen Handgriffs in der Konfiguration bedarf. Sie sollten aber auch bedenken, dass gesetzte Direktiven innerhalb der php.ini systemweite Wirkung entfalten (können). Daher ist es ratsam, hier in Abwägung des mehrheitlichen Nutzen aller Scripte zu konfigurieren.
Kontrollieren Sie Ihre Konfiguration mit der Funktion phpinfo() (oder mit dem Parameter -i, wenn Sie mit dem CLI an der Kommandozeile arbeiten). phpinfo() gibt Ihnen alle erheblichen System-, Server-, Umgebungsvariablen- und Konfigurationangaben aus:
<?php phpinfo(4); # Hauptdirektiven phpinfo(8); # Direktiven und Angaben eingebundener Erweiterungen ?>
Hinweis: Das Komandozeilenprogramm PHPs (CLI) parst nur Dateien mit Namen php-cli.ini.
[Bearbeiten] Syntax
Die Syntax der php.ini gestaltet sich erfreulich übersichtlich:
- Direktiven
- Direktiven bestehen aus dem Paar Name und Wert, die durch ein Gleichheitszeichen "=" voneinander getrennt werden.
Lesen Sie mehr zu den einzelnen Direktiven unter Alphabetische Liste der Direktiven.
asp_tags=Off
- Kommentare
- Ein Kommentar beginnt mit ein Semikolon ";". Er endet mit dem Zeilenende. Zeilenübergreifende Kommentare gibt es in PHP nicht.
Direktive=Wert ; Kommentar
- Sektionen
- Sektionen werden durch einen Text umschlossen von einem Paar Eckiger Klammern ("[" und "]") festgelegt. Sie entfalten für die Steuerung PHPs keinerlei Wirkung und sind nur für die Ausgabe der Funktion parse_ini_file() von Bedeutung.
[Sektion_1]
- Variablen
- Alle Direktiven können als Variable innerhalb der php.ini eingesetzt werden. Ein Variable setzt sich aus dem Dollarzeichen "$" gefolgt vom in einem Paar Geschweifter Klammern ("{" und "}") notierten Direktivennamen, dessen Inhalt verwendet werden soll. Diese Möglichkeit steht Ihnen erst seit der Version 5.1 zur Verfügung.
open_basedir=${include_path}":/ein/anderer/pfad"
[Bearbeiten] Wohin muss die php.ini
Hinweis: Wurde PHP als Apache-Modul (Version 1.3.x) unter der configure-Option des Apachen --activate-module installiert, werden keinerlei Einstellungen der php.ini beachtet. Sie können PHP in diesem Fall nur über die Konfigurationsdateien des Apachen abstimmen. Lesen sie dazu mehr im nächsten Abschnitt Konfiguration unter Apache.
Die Verzeichnisse, unter denen PHP vor der Ausführung von Scripten nach Konfigurationen sucht, werden dem configure-Script mit den Optionen --with-config-file-path und --with-config-file-scan-dir mitgeteilt und sind nach dem Compilieren nicht mehr veränderbar. Wenn Sie also wissen wollen, wo Sie Ihre php.ini ablegen müssen, führen Sie folgendes Script aus und suchen Sie die entsprechenden Optionen in den Spalte für Configure Command und Configuration File:
<?php phpinfo(1); ?>
Eine mögliche Ausgabe könnte so aussehen:
| System | Linux eddi.to-grip.de 2.6.16.9 #1 Tue Apr 19 12:00:01 CEST 2006 x86_64 |
| Build Date | Jan 19 2006 04:16:00 |
| Configure Command | './configure' '--disable-all' '--disable-short-tags' '--enable-memory-limit' '--enable-sysvsem' '--enable-sysvshm' '--with-apxs2=/usr/local/apache/bin/apxs' '--with-bz2' '--with-config-file-path=/etc' '--with-openssl' '--with-zend-vm=GOTO' '--with-zlib' |
| Server API | Apache 2.0 Handler |
| Virtual Directory Support | enabled |
| Configuration File (php.ini) Path | /etc/php.ini |
| PHP API | 20041225 |
| PHP Extension | 20050922 |
| Zend Extension | 220051025 |
| Debug Build | no |
| Thread Safety | enabled |
| Zend Memory Manager | enabled |
| IPv6 Support | enabled |
| Registered PHP Streams | php, file, http, ftp, compress.bzip2, compress.zlib, https, ftps |
| Registered Stream Socket Transports | tcp, udp, unix, udg, ssl, sslv3, sslv2, tls |
| Registered Stream Filters | string.rot13, string.toupper, string.tolower, string.strip_tags, convert.*, consumed, bzip2.*, zlib.* |
Zend Engine v2.1.0, Copyright (c) 1998-2006 Zend Technologies
Hinweis: Die Konfiguration der Direktive expose_php lässt sich ausschließlich in der php.ini vornehmen.
[Bearbeiten] Konfiguration unter Apache
Um PHP durch die Serverkonfigurationsdateien (httpd.conf/.htaccess) steuern zu können, muss PHP als Servermodul installiert sein. Wenn Sie sich nicht sicher sind, mit welchem SAPI Sie es zu tun haben, führen Sie folgendes Script aus:
<?php echo php_sapi_name(); ?>
Mögliche Ausgaben dieses Scripts sind dabei cgi, cgi-fcgi, apache2handler, apache2filter oder apache. Folgende Beschreibung gilt also nur für die letzten drei SAPIs. Für die Konfiguration der CGI-Binäre lesen Sie bitte Apache: PHP als CGI.
[Bearbeiten] PHP als Webservermodul
Als Apache-Modul setzt PHP einige Konfigurationsdirektiven, die Ihnen im folgenden erklärt werden:
- php_value name value
- Setzt den angegebenen Wert value für die mit name angegebene PHP-Direktive. Diese Direktive kann in allen Konfigurationsdateien (httpd.conf/.htaccess) des Apachen für die Steuerung von PHP-Direktiven verwendet werden, den Wertetyp string oder integer haben, und deren Änderbarkeit auf PHP_INI_ALL | PHP_INI_PERDIR gesetzt ist.
- php_flag name on/off
- Setzt den angegebenen Wert value für die mit name angegebene PHP-Direktive. Diese Direktive kann in allen Konfigurationsdateien (httpd.conf/.htaccess) des Apachen für die Steuerung von PHP-Direktiven verwendet werden, den Wertetyp boolean haben, und deren Änderbarkeit auf PHP_INI_ALL | PHP_INI_PERDIR gesetzt ist.
- php_admin_value name value
- Setzt den angegebenen Wert value für die mit name angegebene PHP-Direktive, sodass dieser sich nicht mehr mit Angaben in .htaccess-Dateien überschreiben lässt. Diese Direktive kann in der zentralen Konfiguration (httpd.conf) des Apachen für die Steuerung von PHP-Direktiven verwendet werden, den Wertetyp string oder integer haben, und deren Änderbarkeit auf PHP_INI_ALL | PHP_INI_PERDIR | PHP_INI_SYSTEM gesetzt ist.
- php_admin_flag name name on/off
- Setzt den angegebenen Wert value für die mit name angegebene PHP-Direktive, sodass dieser sich nicht mehr mit Angaben in .htaccess-Dateien überschreiben lässt. Diese Direktive kann in der zentralen Konfiguration (httpd.conf) des Apachen für die Steuerung von PHP-Direktiven verwendet werden, den Wertetyp boolean haben, und deren Änderbarkeit auf PHP_INI_ALL | PHP_INI_PERDIR | PHP_INI_SYSTEM gesetzt ist.
Ein Beispiel für die Konfiguration eines Virtual-Hosts:
<VirtualHost 127.0.0.1:80>
ServerName localhost
ServerAlias mein.server
DocumentRoot /var/www/default
<Directory /var/www/default>
AllowOverride All
php_value include_path ".:/var/www/inc:/var/www/default/inc"
php_admin_value memory_limit 2M
php_admin_value open_basedir /var/www/default
php_admin_value post_max_size 100K
php_admin_flag safe_mode On
php_admin_value upload_max_filesize 0
php_admin_value upload_tmp_dir /var/www/uploads
</Directory>
<Directory /var/www/default/html>
php_admin_flag file_uploads Off
</Directory>
<Directory /var/www/default/upload>
php_admin_value doc_root /var/www/default/upload
php_admin_flag file_uploads On
php_admin_value include_path "."
php_admin_value post_max_size 14M
php_admin_value upload_max_filesize 12M
</Directory>
# Andere Angaben
</VirtualHost>
[Bearbeiten] PHP als CGI
Die CGI-Binäre PHPs werden über die php.ini konfiguriert, daher werden Ihnen in diesem Abschnitt nur Tricks vorgestellt, wie Sie spezielle Konfigurationen umsetzen können.
Bis vor einigen Jahren suchte PHP im jeweiligen Script-Verzeichnis nach einer Konfigurationsdatei. Leider ist diese überaus praktische Funktionalität in neueren Versionen aus Sicherheitsgründen nicht mehr umgesetzt worden. Dafür kann PHP auf Kommandozeilenebene mit einem Parameter -c aufgerufen werden, der als Argument den Pfad zu einer php.ini bzw. zu einem Verzeichnis erwartet.
Also erstellen Sie sich ein kleines Shell-Script, dass PHP mit einer Konfigurationsdateiangabe aufrufen kann:
#!/bin/sh if [ -e /pfad/zu/php ] then scandir=`/bin/dirname ${PATH_TRANSLATED}`; default='/pfad/zur/default_ini/php.ini'; cgiprog='/pfad/zu/php -c' if [ -e "$scandir/php.ini" ] then $cgiprog $scandir; else $cgiprog $default; fi else exit 1; fi exit $?;
Dieses Shell-Script wird im Verzeichnis des PHP-Scriptes nach der Datei php.ini suchen. Ist keine php.ini in diesem Verzeichnis, wird PHP mit einer Default-Konfigurationsdatei (/pfad/zur/default_ini/php.ini) gestartet. Passen Sie die Pfandangaben an Ihre Gegebenheiten an und legen Sie dieses Shell-Script in das Verzeichnis des CGI-Binärs ab. Ich habe das Script startphp.sh genannt.
Als nächstes muss die Konfiguration des Apachen geändert werden, damit PHP nicht mehr direkt aufgerufen wird, sondern das Shell-Script dieses erledigt:
ScriptAlias /wikiphp/ /pfad/zum/php/verzeichnis/ Action application/x-httpd-php /wikiphp/startphp.sh Action application/x-httpd-php-source /wikiphp/startphp.sh
Nach einem Restart des Webservers wird PHP sodann mit der verzeichnisweiten (oder eben mit der default) Konfigurationen gestartet. Insbesondere für Anwendungsentwickler erweist sich diese Vorgehensweise als nützlich. Sie können so an einem lokalen Testserver die jeweiligen Konfigurationen (und auch den entsprechenden Versionen PHPs) verschiedener Produktivumgebungen simulieren.
Wenn Sie selbst Webdienste anbieten, ist dieses Script natürlich nicht für den Einsatz geeignet, da Sie sonst keine Funktionen sperren und andere wirksame Sicherheitsmaßnahmen mehr treffen können. Aber mit einem leicht modifizierten Script wird es Ihnen möglich, jedem Web eine individuelle Konfiguration zu verpassen.
Wie bereits im ersten Script nutzen Sie dazu eine Environmentvariable. Da jedes Web die serverweit eindeutige Variable SERVER_NAME hat, können Sie diese zur Identifikation nutzen. Für alle Webprojekte, denen Sie also eine individuelle Konfiguration zukommen lassen wollen, erstellen Sie in einem Verzeichnis eine eigene Konfigurationsdatei; für alle anderen Webprojekte wird PHP mit default-Konfigurationen gestartet:
#!/bin/sh
if [ -e /pfad/zu/php ]
then
scanini="/pfad/zur/kunden/${SERVER_NAME}.ini";
default='/pfad/zur/default_ini/php.ini';
cgiprog='/pfad/zu/php -c'
if [ -e $scanini ]
then $cgiprog $scanini;
else $cgiprog $default;
fi
else exit 1;
fi
exit $?;
Die Konfigurationsdatei für den Virtualhost localhost heißt also localhost.ini.
[Bearbeiten] Konfiguration innerhalb von Scripten
Die Möglichkeit PHP innerhalb von Scripten zu konfigurieren gehört zu den häufig genutzten. Sie können Ihre Scripte dadurch portabel machen, ohne Einstellungen in Konfigurationsdateien, wie der php.ini, vornehmen zu müssen. Jedoch lassen sich nicht alle Direktiven manipulieren. Unter Konfiguration Grundlegendens wurde Ihnen kurz dargelegt, welche drei Kategorien von Direktiven es gibt. Innerhalb von Scripten können Sie nur Direktiven ändern, deren Änderbarkeit durch die Konstante PHP_INI_ALL repräsentiert wird.
Die beiden folgenden Scripte sind im Resultat analog zueinander:
<?php header('Content-Type: application/xhtml+xml; charset=iso-8859-15',true); ?>
<?php ini_set('default_mimetype','application/xhtml+xml'); ini_set('default_charset', 'iso-8859-15'); ?>
Es wird in beiden Fällen ein HTTP-Header Content-Type gesendet. Auch wenn dies ein schlechtes Beispiel ist, weil diese Konfiguration verzeichnisweit für einen Webauftritt in Konfigurationsdateien gesetzt werden sollte, zeigt Ihnen das zweite Script die Funktion ini_set(). ini_set() ist die wichtigste Funktion, um innerhalb von Scripten Konfigurationen zu manipulieren.
Beachten Sie im Umgang mit ini_set(), das es unterschiedliche Typen von Direktiven gibt. Die Typen sind boolean, integer und string und verhalten sich wie die gleichnamigen Variablentypen:
<?php ini_set('display_errors', false); # boolean ini_set('log_errors_max_len', 128); # integer ini_set('error_log', 'syslog'); # string ?>
Darüber hinaus gibt es noch eine Vielzahl von Funktionen, die eine ganz bestimmte Direktive manipulieren. Wenn Sie diese kennenlernen wollen, sehen Sie sich dazu die Kommentare in der Alphabetische Liste der Direktiven an.
[Bearbeiten] Themenweite Konfiguration
in Bearbeitung!
[Bearbeiten] Der Safe Mode
in Bearbeitung!
[Bearbeiten] File Upload
in Bearbeitung!
[Bearbeiten] Datenkompression für Webserver
Das Hypertexttransfer Protokoll (HTTP 1.1 RFC 2616) bietet die Möglichkeit Daten auch komprimiert auszuliefern. Ein Client (z. B. Ihr Browser) sendet dazu an einen Server im Requestheader Informationen, daß er auch komprimierte Daten akzeptiert und welche Kompressionsverfahren er unterstützt. Gerade zur Sicherung der Bandbreite eines Webservers ist die komprimierte Auslieferung wichtig. PHP sollte daher für Webserver immer mit dem zlib-Modul compiliert werden. Ist PHP mit diesem Modul übersetzt worden, sollten sie dieses Modul auch nutzen!
Konfiguration in der php.ini:
zlib.output_compression =1 zlib.output_compression_level=9
oder Konfiguration am Anfang eines jeden Scripts:
ini_set('zlib.output_compression',1);
ini_set('zlib.output_compression_level',9);
PHP wird dadurch veranlaßt einen internen Ausgabepuffer einzusetzen (die Scriptausgaben aber auch Daten außerhalb der Scriptblöcke werden zwischengespeichert) und nach Beendigung der Scriptausführung die Ausgabe gegebenenfalls zu komprimieren.
[Bearbeiten] PHP auf dem Webserver verschleiern
Es kann viel Gründe dafür geben, die Existenz von PHP auf einem Webserver zu verschleiern. Wenn Sie schon einmal nach einer Fertiglösung in Suchmaschinen suchten, die Sie in PHP haben wollten, werden Sie bereits einen guten Grund kennen. Manche Suchmaschinen neigen dazu auch die URL für Ihr Suchmuster als Treffer heranzuziehen und es wird ihnen ein Haufen belangloser Verweise angeboten, nur weil diese auf .php enden.
Seit 2005 hatten sich auch einige sogenannte "Linux-Würmer" darauf spezialisiert Suchmaschinen gezielt nach schlecht geschriebenen Scripten zu durchsuchen, um sich zu vermehren. Daher kann das Verschleiern auch ein wenig mehr Sicherheit bringen.
Für einen Besucher einer Internetpräsenz ist natürlich die Dateiendung .php ein deutliches Zeichen auf die eingesetzte Technik. Aber genaugenommen braucht kein Mensch die Dateiendungen, um durch Inhalte zu browsen. Daher ist eine URL der Form www.domain.de/verzeichnis/datei genauso aussagekräftig, wie www.domain.de/verzeichnis/datei.php. Nehmen Sie dazu in Ihre Apache-Konfiguration folgendes auf:
Options +MultiViews
Dies wird mod_negotiation für die Abarbeitung eines Requests auf den Plan rufen. Sollte dieses Modul nicht in den Webserver eincompiliert oder geladen worden sein, können Sie nur die Dateiendungen abändern:
application/x-httpd-php xhtm xhtml
Natürlich können Sie auch mod_rewrite nutzen oder sich des unter Pseudo-URLs durch PATH_INFO gezeigten Tricks bedienen.
Sollten Sie aus sicherheitstaktischen Gründen PHP verschleiern wollen, so sein Sie hiermit gewarnt. Es reicht nicht aus nur die Dateiendungen zu verbergen. Die Anwesenheit PHPs schlägt sich auch in HTTP-Headern nieder. So erzeugt die erste Beispielkonfiguration folgende Header:
HTTP/1.1 200 OK Date: Sun, 14 May 2006 06:36:26 GMT Server: Apache/1.3.35 (Unix) PHP/5.1.4 Content-Location: test.php TCN: choice Vary: negotiate,accept Connection: close X-Powered-By: PHP/5.1.4 Transfer-Encoding: chunked Content-Type: text/plain;charset=iso-8859-1
Die Header Content-Location, TCN und Vary rühren dabei vom mod_negotiation. X-Powered-By und der Anhang im Server-Header kommen aber von PHP selbst. Diese können durch die Direktive expose_php in der php.ini deaktiviert werden.
[Bearbeiten] Pseudo-URLs durch PATH_INFO
Die hier vermittelten Informationen fordern von Ihnen schon gefestigte Kenntnisse im Umgang mit PHP. Wenn Sie mit PHP beginnen wollen und dieses Wikibook in chronologischer Reihenfolge lesen, wird Sie dieser Abschnitt überfordern. Sie werden noch an einigen Stellen dieses Wikibooks auf Informationen stoßen, die Sie nicht auf Anhieb verstehen werden. Lassen Sie sich davon nicht beirren, sondern kehren Sie mit dem später erworbenen Wissen an diese Stellen wieder zurück!
Dieser Abschnitt könnte auch die Überschrift Machen Sie mod_rewrite arbeitslos haben. mod_rewrite ist ein beliebtes Apache-Modul, das Anfragen an Ressourcen umformulieren kann. Dadurch ist es möglich Pseudolinks in einem Webprojekt einzubetten, die es reell gar nicht gibt. Nur wer braucht schon dieses Modul, wenn er bereits PHP hat? ;)
Legen Sie also eine .htaccess in das oberste Web-Verzeichnis mit folgendem Inhalt:
<Files meinwiki>
ForceType application/x-httpd-php
AcceptPathInfo On
</Files>
Diese Konfiguration wird den Apache veranlassen die Datei meinwiki wie ein PHP-Script zu behandeln. Erstellen Sie nun das Script meinwiki:
<?php $a=array('application/xhtml+xml'=>array('xhtm','xhtml'), 'application/xml' =>array('xml'), 'text/plain' =>array('txt','asc'), 'text/html' =>array('htm','html','php','phtml') ); $pfad='.'.str_replace('../',"",$_SERVER['PATH_INFO']); if($pfad=='.' || (is_dir($pfad) && substr($pfad,-1)!='/')){ $pfad ='http'.(isset($_SERVER['HTTPS']) ? 's' : "").'://'; $pfad.=$_SERVER['HTTP_HOST']; $pfad.=str_replace('../',"",$_SERVER['REQUEST_URI']).'/'; header('Location: '.$pfad,true,301); exit; } elseif(is_dir($pfad)){ foreach($a as $k=>$v) for($i=0;$i<count($v);$i++) if(file_exists($pfad.'index.'.$v[$i])){ header('Content-Type: '.$k); if($v[$i]{0}=='p') require($pfad.'index.'.$v[$i]); else readfile($pfad.'index.'.$v[$i]); exit; } } elseif(file_exists($pfad) && substr($pfad,-1)!='/'){ $x=pathinfo($pfad); foreach($a as $k=>$v) if(in_array($x['extension'],$v)){ header('Content-Type: '.$k); if($x['extension']{0}=='p') require($pfad); else readfile($pfad); } exit; } $cgi=(substr(php_sapi_name(),0,3)=='cgi') ? true : false; header(($cgi ? 'Status: 404' : 'HTTP/1.1 404 Not Found'),true,404); echo '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">'. '<html><head><title>404 Not Found</title></head>'. '<body>< h1>Not Found< /h1>< p>The requested URL '. $_SERVER['REQUEST_URI']. ' was not found on this server.< /p></body></html>'; ?>
Wenn es in Ihrem DocumentRoot beispielsweise ein Verzeichnis test/ gibt, dann können Sie jetzt sowohl http://[domain]/test/, als auch http://[domain]/meinwiki/test/ in einem Browser aufrufen. Dieses Script macht also nichts außergewöhnliches, es erstellt nur auf Scriptebene die selbe Funktionalität, die der Webserver verwendet, um eine angeforderte Ressource aufzusuchen, bereit. Dies lässt sich ausnutzen, um Ressourcen außerhalb des eigenen Webverzeichnisses einzubinden:
$pfad='/home/eddi/public_html'.str_replace('../',"",$_SERVER['PATH_INFO']);
Sie können aber auch die Pfadangaben, wie mod_rewrite es tun würde, in Variablen zerlegen:
list($_GET['param'], $_GET['datei'], $_GET['vname'])=explode('/',str_replace('../',"",$_SERVER['PATH_INFO']));
Dieses entspricht folgender Rewrite-Rule:
RewriteEngine On RewriteRule ^meinwiki/(.*)/(.*)/(.*) scriptname.php?param=$1&datei=$2&vname=$3
mod_rewrite - Paul?! Wer ist eigentlich Paul? ;)
Somit kommen auch Nutzer des IIS in den Genuß einer Rewriteengine.

