Websiteentwicklung: PHP: Konfiguration
Grundlegendes
[Bearbeiten]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 von PHP 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 Quellcodes bestimmt werden.
- Erläuterung der Konstanten
- PHP_INI_ALL
- Ist eine PHP-Direktive mit dieser Konstante implementiert worden, kann sie in Skripten (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 Skripten 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.
Die Konfigurationsdatei php.ini
[Bearbeiten]Die php.ini ist die zentrale Konfigurationsdatei durch die alle Verhaltensregeln von PHP festgelegt werden. Innerhalb des Quellcodes 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 Skripte 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 PHP-Komandozeilenprogramm (CLI) parst nur Dateien mit Namen php-cli.ini.
Syntax
[Bearbeiten]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 von PHP 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"
Wohin muss die php.ini
[Bearbeiten]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 Skripten nach Konfigurationen sucht, werden dem configure-Skript mit den Optionen --with-config-file-path und --with-config-file-scan-dir mitgeteilt und sind nach dem Kompilieren nicht mehr veränderbar. Wenn Sie also wissen wollen, wo Sie Ihre php.ini ablegen müssen, führen Sie folgendes Skript 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.
Konfiguration unter Apache
[Bearbeiten]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 Skript aus:
<?php echo php_sapi_name(); ?>
Mögliche Ausgaben dieses Skripts 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.
PHP als Webservermodul
[Bearbeiten]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>
PHP als CGI
[Bearbeiten]Die CGI-Binäre von PHP 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 Skript-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-Skript, 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-Skript wird im Verzeichnis des PHP-Skriptes 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-Skript in das Verzeichnis des CGI-Binärs ab. Ich habe das Skript startphp.sh genannt.
Als nächstes muss die Konfiguration des Apachen geändert werden, damit PHP nicht mehr direkt aufgerufen wird, sondern das Shell-Skript 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 PHP-Versionen) verschiedener Produktivumgebungen simulieren.
Wenn Sie selbst Webdienste anbieten, ist dieses Skript 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 Skript wird es Ihnen möglich, jedem Web eine individuelle Konfiguration zu verpassen.
Wie bereits im ersten Skript nutzen Sie dazu eine Umgebungsvariable. 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.
Konfiguration innerhalb von Skripten
[Bearbeiten]Die Möglichkeit, PHP innerhalb von Skripten zu konfigurieren, gehört zu den häufig genutzten. Sie können Ihre Skripte 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 Skripten können Sie nur Direktiven ändern, deren Änderbarkeit durch die Konstante PHP_INI_ALL repräsentiert wird.
Die beiden folgenden Skripte 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 Skript die Funktion ini_set(). ini_set() ist die wichtigste Funktion, um innerhalb von Skripten 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.
Themenweite Konfiguration
[Bearbeiten]in Bearbeitung!
Der abgesicherte Modus
[Bearbeiten]in Bearbeitung!
Dateien hochladen
[Bearbeiten]in Bearbeitung!
Datenkompression für Webserver
[Bearbeiten]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 Anfrageheader Informationen, dass 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 kompiliert 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 Skripts:
ini_set('zlib.output_compression',1);
ini_set('zlib.output_compression_level',9);
PHP wird dadurch veranlaßt, einen internen Ausgabepuffer einzusetzen (die Skriptausgaben aber auch Daten außerhalb der Skriptblöcke werden zwischengespeichert) und nach Beendigung der Skriptausführung die Ausgabe gegebenenfalls zu komprimieren.
PHP auf dem Webserver verschleiern
[Bearbeiten]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 Skripten 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 einkompiliert 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 seien Sie hiermit gewarnt. Es reicht nicht aus, nur die Dateiendungen zu verbergen. Die Anwesenheit von PHP 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.
Pseudo-URLs durch PATH_INFO
[Bearbeiten]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-Skript zu behandeln. Erstellen Sie nun das Skript 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) != '/')) {
$protokol = 'http'. (isset($_SERVER['HTTPS']) ? 's' : '') .'://';
$host = $_SERVER['HTTP_HOST'];
$pfad = str_replace('../', '', $_SERVER['REQUEST_URI']) .'/';
header('Location: '. $protokol . $host . $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">';
echo '<html>';
echo '<head>';
echo '<title>404 Not Found</title>';
echo '</head>';
echo '<body>';
echo '<h1>Not Found</h1>';
echo '<p>The requested URI '. $_SERVER['REQUEST_URI'] .'was not found on this server.</p>';
echo '</body>';
echo '</html>';
?>
Sie können aber auch die Pfadangaben, wie mod_rewrite es tun würde, in Variablen zerlegen:
$pfad = str_replace('../', '', $_SERVER['PATH_INFO']);
list($_GET['param'], $_GET['datei'], $_GET['vname']) = explode('/', $pfad);
Dieses entspricht folgender Rewrite-Regel:
RewriteEngine On RewriteRule ^meinwiki/(.*)/(.*)/(.*) scriptname.php?param=$1&datei=$2&vname=$3
Somit kommen auch Nutzer des IIS in den Genuß einer Rewriteengine.