WordPress Blog von http auf https umstellen

Hier möchte ich kurz beschreiben wie man seinen WordPress Blog von http:// auf https:// umstellen kann. Voraussetzung ist, dass für die Blog Domain bereits ein Zertifikat eingerichtet ist. Also die Domain schon unter https://domain.tld erreichbar ist. Die Website, die ich hier für die Umstellung nehme, ist die von meinem Schwager, da ich meine bereits umgestellt habe.

Es wird nicht nur das Backend umgestellt, sondern die ganze Webseite.
Deshalb müssen auch keine Konstanten in der wp-config.php definiert werden.
Durch das umstellen der ganzen Webseite wird sich das positiv auf das Google Ranking auswirken und auch Besuchern eine höhere Sicherheit angezeigt. Natürlich kommt hinzu, dass keine Daten mehr unverschlüsselt übertragen werden, was ja nicht nur bei Shops interessant ist.

Zur Umstellung:

Im Backend unter „Einstellungen > Allgemein“ die URLs von http://… aud https://… ändern und Speichern. Danach wieder neu Anmelden.
Falls die Felder ausgegraut sind habt ihr diese in der wp-config.php definiert und müsst sie dort ändern.

wp_ssl_umstellem_1

Eigentlich war das schon das wesentliche. Allerdings müssen wir jetzt noch den bestehenden Content anpassen. Dies machen wir mittels Search&Replace in der Datenbank.

Ich verwende dafür, da es sich für mich bewährt das Better Search Replace Plugin. Also das Plugin installieren und Aktivieren.

wp_ssl_umstellem_2

Dann unter „Werkzeuge > Better Search Replace“ öffnen. Bei „Suchen nach“ die Alte Blog URL eintragen und bei „Ersetzen durch“ die gleiche URL nur mit https. Bitte immer die vollständige Blog URL verwenden da es sonst zu Problemen kommen kann.
Danach alle Tabellen auswählen und den Haken bei „Auch GUIDs ersetzen“ setzen. Es kann nach Wunsch auch erst ein Testlauf gemacht werden. Damit die Änderungen endgültig durchgeführt werden, muss der Haken auf jeden Fall entfernt werden.
Man sollte vorher natürlich seine Datenbank sichern!

wp_ssl_umstellem_3

Nachdem die Änderungen durchgeführt wurden erscheint folgende Meldung

wp_ssl_umstellem_4

Damit sollten jetzt alle Blog URLs von http auf https umgestellt sein und das Plugin kann wieder deaktiviert und deinstalliert werden.

In Chrome sollte die Webseite dann mit einem grünen Schloss angezeigt werden.
Wenn nicht alle Inhalte mittels https ausgeliefert werden, ist das Schloss grau und nicht grün. Man erhält in der URL-Leiste einen Hinweis. Wenn das der Fall ist, muss noch in seinen Anpassungen (Widgets, PHP Dateien, usw.) suchen, ob dort noch URLs enthalten sind, die nicht mit https anfangen und diese umstellen.

wp_ssl_umstellem_5

Zusätzlich sollte man jetzt noch alle Aufrufe der Webseite auf die https URL umleiten. Dafür kann man mit folgendem Eintrag zusätzlich in die .htacssess einfügen.

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>

Viel Spaß beim Umstellen.

Einfacher PHP Objekt Cache – APCu einrichtung

Viele kennen vielleicht den APC Cache von PHP noch. Dieser wurde zum Cachen von PHP Skripten und als Objekt Cache genutzt. Heute übernimmt allerdings der Opcode Cache die Aufgabe des Cachens von PHP Skripten und würde sich daher mit APC in Gehege kommen. Daher wurde der Objekt Cache (Userland Cache) aus APC herausgelöst und als APCu herausgebracht.

Ich verwende APCu gerne als Objekt Cache da es sich so leicht einrichten lässt und kein extra Dienst notwendig ist.

Für die Einrichtung benötigt man die zu seiner PHP Version passende dll. Diese findet man hier. Aus dem ZIP Archiv benötigen wir nur die php_apcu.dll, diese Kopiere ich mir in dem „extras“ Ordner der sich im PHP Verzeichnis befindet.

Dan müssen wir die php.ini bearbeiten und die dll als Extension in der [PHP] Section hinzufügen:

extension=C:/php/extras/php_apcu.dll

Dann müssen wir noch eine Section wie folgt erstellen:

[apcu]
apc.enable_cli = on
apc.enabled = on
apc.writable = "C:/Temp/"

Dies reicht um APCu zu aktivieren. Der Webserver sollte einmal neu gestartet werden.

Damit man den Cache überhaut nutzen kann muss man ihn im CMS aktivieren. Das geht in WordPress indem man eine object-cache.php Datei im wp-content ablegt. In WordPress kann man direkt einen Geschwindigkeitsunterschied merken auch wenn noch nicht viel im Blog ist.

Um zu sehen was im Cache ist kann man sich die Datei auf dem Webserver ablegen und Aufrufen.

Den APCu Cache wird man bei Standard Shard Hosting nicht finden da der Cache immer für alle auf dem Server gilt und es somit ein Sicherheitsrisiko darstellt. Bei Mittwald kann man allerdings APCu in den Managet Server Paketen bekommen.

WordCamp Europe 2015 Sevilla – Spanien

 

IMG_0371

 

Mein Besuch auf dem WordCamp Europe 2015 in Sevilla – Spanien war fantastisch! Zusammen mit Detlef Heese und Annette Völckner  sind wir schon am Dienstag vor dem Start des WordCamps angereist, um auch ein paar Tage Sevilla genießen zu können.

Dienstag:

Über Frankfurt ging es nach Sevilla. Die erste Überraschung erlebten wir als wir ins Hotel eincheckten. Dort wollte uns die Managerin vom Barceló Sevilla Renacimiento Hotel sprechen. Sie hat uns persönlich in dem 5 Sterne Hotel willkommen geheißen. Nachdem wir die Zimmer bezogen hatten, haben wir uns erstmal bei Temperaturen von 31°C am Hotelpool getroffen, um uns von der Reise zu erholen.

Abends sind wird dann in die Stadt zum Tapas essen gegangen und haben den Abend mit ein paar Guinness ausklingen lassen.

 

Mittwoch:

Dieser Tag war der totalen Entspannung gewidmet. Außerdem sind noch einige Leute aus der deutschen Community eingeflogen.  Am frühen Abend wurden erst noch ein paar Runden mit Dominik Schilling durch den Pool gedreht bevor es dann weiter zum Tapas essen in der Innenstadt ging. Dabei sind dann noch diese wunderbaren Bilder von Detlef entstanden.

Donnerstag:

Auch an diesem Tag bin ich tagsüber die meiste Zeit am Pool gewesen. Während Detlef noch mit ein paar weiteren Leuten zum Expo Gelände aufgebrochen ist, um sich dieses anzusehen. Abends ging es natürlich wieder in die Stadt zum Tapas essen. An diesem Tag wurde es allerdings nicht so spät, da ja am nächsten Morgen das WordCamp startete.

Freitag:

Tag eins des WordCamp Europe: Erstmal registrieren. Danach ging der Ansturm auf die Sponsoren los, die ein paar Geschenke zu verteilen hatten. Da das Camp ja direkt in unserem Hotel stattfand, konnte ich die Give-aways dann direkt auf Zimmer bringen und musste sie nicht mit mir herumtragen. Danach ging es dann mit den Vorträgen los. Am schönsten fand ich den von Zeev Suraski über die Geschichte von PHP 7. Natürlich waren auch alle anderen Vorträge sehr gut. Abends ging es natürlich wieder …

Samstag:

Tag zwei des WordCamp Europe: Heute ging es mit Vorträgen weiter. Am besten haben mir der über die WordPress REST-API gefallen und einige short Talks. Die Vorträge hatte ich nicht geschafft mir auf dem WordCamp in Köln anzusehen. Aber auch alle anderen Vorträge an diesem Tag waren sehr gut. Abends ging es dann zur After Party in einer Disco in Sevilla. Dort wurde sehr ausgiebig gefeiert. Da dort allerdings auch einheimische Gäste zur selben Zeit Zutritt hatten, wurde es sehr voll. Deshalb ging ich mit einigen Leuten noch weiter ….

FullSizeRender

Sehr gefreut habe ich mich dann noch als Gino Cremer mir sein WordPress Praxishandbuch mit persönlicher Signierung überreichte als Dankeschön für die Entwicklung von BackWPup.

Sonntag:

Contributor Tag: Leider für uns der Tag der Abreise, da Detlef und ich am Montag wieder arbeiten mussten. Mittlerweile sind es in Sevilla tagsüber 42°. Viel trinken war die Devise auf dem WordCamp. Gott sei Dank waren die Konferenzräume klimatisiert.

Fazit:

Für mich war es ein wunderbares WordCamp Europe. Ich durfte so viele Leute aus der deutschsprachigen Community näher kennenlernen und alte Bekanntschaften auffrischen. Das war für mich das allerbeste an diesem WordCamp; nur dass ich dafür extra nach Sevilla fliegen musste.

Das nächste WordCamp Europe ist übrigens in Wien.

 

An dieser Stelle möchte ich mich nochmal bei meiner Frau bedanken, die leider zu Hause bleiben musste, um sich um unsere Kinder zu kümmern.

WordPress Sicherheit erhöhen ohne Plugins

Ich bin der Meinung, dass man die Sicherheit von WordPress auch ohne Plugins erhöhen kann. Oder andersherum: Hackern und automatisierten Angriffen das Leben schwerer machen. Wie das geht, werde ich hier beschreiben.

Eins vorweg: Wenn man keine sicheren Passwörter verwendet, nützt einem auch die beste Absicherung nichts. Und das gilt nicht nur für deinen WordPress Zugang, sonder für alle Zugangsmöglichkeiten zu Webspace (FTP, SSH, MySQL, …). Außerdem bietet heute nahezu jeder Hoster die Möglichkeit Daten verschlüsselt zu übertragen. Insbesondere bei E-Mail oder FTP.

Die Installation:

Ich habe WordPress in einem unter Ordner installiert.  Ich bin der Meinung, wenn man diese Art der Installation wählt, hat ein automatisierter Angriff es zumindest etwas schwerer den WordPress Ordner zu finden. Außerdem finde ich es etwas aufgeräumter, da ich in dem Root Ordner noch weitere Dienste installiert habe, damit ich sie alle mit einem https Zertifikat nutzen kann. Dazu kommt noch, dass ich den „wp-content“ Ordner umbenannt habe.FTP-Ordner-wp-subfolder-install

Um den „wp-content“ Ordner umzuebnen, bedarf es zwei Einträge in der „wp-config.php“.

define( 'WP_CONTENT_DIR', realpath( dirname(__FILE__) . '/../content' ) );
define( 'WP_CONTENT_URL', 'https://dhue.de/content' );

Dies sollten heute alle Plugins unterstützen.

Zusätzliche Absicherungen:

.htaccess im Root (Haupt) Ordner.

<FilesMatch "(.htaccess|readme.html|liesmich.html|license.txt|license.md|readme.txt|readme.md|wp-config.php)"> Deny from all </FilesMatch> php_flag display_errors off

Der „FilesMatch“ Eintrag sorgt dafür, dass auf die Dateien in der Liste nicht direkt über eine URL zugegriffen werden kann. Hier sind auch die Readme Dateien enthalten, damit man darüber nicht erkennen kann, ob etwas vorhanden ist oder sogar die Version herausbekommt.

Die letzte Zeile sorgt dafür, dass PHP keine Fehlermeldungen ausgibt und man somit den Server Pfad nicht in Erfahrung bringen kann.

Im neuen „Content“ Ordner habe ich eine zusätzliche .htaccess liegen mit folgenden Einträgen.

<Files *.php>
 order allow,deny
 deny from all
</Files>
<Files debug.log>
 Order allow,deny
 Deny from all
</Files>

Das sorgt dafür, dass keine .php Dateien mehr direkt im „Content“ Ordner aufgerufen werden können. Allerdings muss hier getestet werden, ob auch alle Plugins und Themes damit funktionieren. Gute Plugins und Themes sollten aber kein Problem damit haben. Alle anderen Dateiformate können weiterhin direkt aufgerufen werden.

WordPress verschleiern:

Mit diesem Stück Code kann man noch einiges im HTML Kopf der Website verbergen oder dekatieren. Dieser kann in die funktions.php eures Child Themes geschrieben werden oder eben doch in ein Kleins Plugin. Hier bitte selber entscheiden, was ihr braucht oder nicht. Der wichtigste Punkt ist hier der „wp_generator“ da dieser auf jeder Seite im HTML  folgendes im Kopf hinzufügt <meta name="generator" content="WordPress 4.1" />.

// Head cleanup
function dh2015_head_cleanup() {
   // category feeds
   //remove_action( 'wp_head', 'feed_links_extra', 3 );
   // post and comment feeds
   //remove_action( 'wp_head', 'feed_links', 2 );
   // EditURI link
   remove_action( 'wp_head', 'rsd_link' );
   // windows live writer
   remove_action( 'wp_head', 'wlwmanifest_link' );
   // index link
   remove_action( 'wp_head', 'index_rel_link' );
   // previous link
   remove_action( 'wp_head', 'parent_post_rel_link', 10, 0 );
   // start link
   remove_action( 'wp_head', 'start_post_rel_link', 10, 0 );
   // links for adjacent posts
   remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0 );
   // WP version
   remove_action( 'wp_head', 'wp_generator' );
}
add_action( 'init', 'dh2015_head_cleanup' );

Anmerkung:

Darüber hinaus sollten natürlich auch das nicht benutzen des Standard DB Präfixes und das Rechte setzen der Ordner Berechtigungen nicht fehlen. Es gibt einen Artikel auf WordPress.org über das abhärten von WordPress der auch durchgegangen werden sollte.

WordPress Links Menü Walker

Hier eine kleine Walker Klasse für WordPress, um sich ein Menü in der Form “ Link1 | Link2 | Link3 “ zu erstellen.

Einfach die Klasse in die functions.php des Themes und den Menü Eintrag dort im Template platzieren, wo er hin soll.

<?php
wp_nav_menu(
   array(
      'container'      => FALSE,
      'menu'           => 'The Footer Links',
      'menu_class'     => 'nav',
      'theme_location' => 'footer-nav',
      'items_wrap'     => '<nav id="%1$s" class="%2$s" role="navigation">%3$s</nav>',
      'depth'          => 1,
      'walker'         => new Links_Walker_Nav_Menu()
   )
);

class Links_Walker_Nav_Menu extends Walker_Nav_Menu {

   function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {

      //Add attributes to link element.
      $attributes = ! empty( $item->attr_title ) ? ' title="' . esc_attr( $item->attr_title ) . '"' : '';
      $attributes .= ! empty( $item->target ) ? ' target="' . esc_attr( $item->target ) . '"' : '';
      $attributes .= ! empty( $item->xfn ) ? ' rel="' . esc_attr( $item->xfn ) . '"' : '';
      $attributes .= ! empty( $item->url ) ? ' href="' . esc_attr( $item->url ) . '"' : '';
      $attributes .= ( $item->current ) ? ' class="active"' : '';

      $output .= ( $item->menu_order > 1 ) ? ' | ' : '';
      $output .= '<a' . $attributes . '>';
      $output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
      $output .= '</a>';

   }

   function end_el( &$output, $item, $depth = 0, $args = array() ) {

      $output .= '';
   }

}

Standard WordPress Plugin Funktionen

Zwei der Funktionen/Methoden, die man in Zukunft wohl in allen meinen Plugins finden wird, sind:
Voraussetzung ist PHP 5.1.2 für die Autoload Funktion.

1. Zum Ermitteln von Plugin Daten, damit nicht immer alles per Constante definiert wird, um Namensraum freizuhalten:

<?php
public static function get_plugin_data( $get_data = FALSE ) {

	$plugin_data = wp_cache_get( 'plugin_data', 'pluginname' );
	if ( $plugin_data === FALSE || empty( $plugin_data[ 'Version' ] ) ) {
		$plugin_data               = get_file_data(
			__FILE__, array(
				'Name'        => 'Plugin Name',
				'PluginURI'   => 'Plugin URI',
				'Version'     => 'Version',
				'Description' => 'Description',
				'Author'      => 'Author',
				'AuthorURI'   => 'Author URI',
				'TextDomain'  => 'Text Domain',
				'DomainPath'  => 'Domain Path'
			), 'plugin'
		);
		$plugin_data[ 'BaseName' ] = plugin_basename( __FILE__ );
		$plugin_data[ 'Folder' ]   = dirname( plugin_basename( __FILE__ ) );
		$plugin_data[ 'URL' ]      = plugins_url( '', __FILE__ );
		if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
			$plugin_data[ 'JSVersion' ] = time();
		} else {
			$plugin_data[ 'JSVersion' ] = $plugin_data[ 'Version' ];
		}
		wp_cache_add( 'plugin_data', $plugin_data, 'pluginname' );
	}

	if ( ! $get_data ) {
		return $plugin_data;
	}

	return $plugin_data[ $get_data ];
}

2. Die Autoload Funktion von PHP zum automatischen Laden von Klassen, damit sie nur dann geladen werden, wenn sie auch benötigt werden. Das heißt, verwendet man ein „add_action“ wird die Klasse erst geladen, wenn wirklich ein „do_action“ erfolgt oder die Seitenklasse für einen Menüeintrag erst geladen wird, wenn der Menüpunkt tatsächlich aufgerufen wird. Voraussetzung ist, dass man das ganze Plugin klassenbasierend aufbaut. Das kann dann nicht nur Ressourcen sparen.

<?php
public function __construct() {
	//register autoloader
	spl_autoload_register( array( $this, 'autoloader' ) );
}

public static function autoloader( $class_name ) {
	//WordPress classes loader
	$wpclass='/class-'.strtolower(str_replace('_','-',$class_name)).'.php';
	if ( is_file(ABSPATH .'wp-admin'.DIRECTORY_SEPARATOR.'includes'.$wpclass) ) {
		require(ABSPATH .'wp-admin'.DIRECTORY_SEPARATOR.'includes'.$wpclass);
		return true;
	}
	if ( is_file(ABSPATH . WPINC . $wpclass) ) {
		require(ABSPATH . WPINC . $wpclass);
		return true;
	}

	//Plugin classes to load
	if ( strpos( $class_name,'PluginClass_') !== false ) {
		$class_load = dirname( __FILE__ ) . DIRECTORY_SEPARATOR.'inc'.DIRECTORY_SEPARATOR.'class-' . strtolower( str_replace( array( 'PluginClass_', '_' ), array( '', '-' ), $class_name ) ) . '.php';
		if ( is_file( $class_load ) ) {
			require($class_load);
			return true;
		}

	}
	return false;
}

Diese sollten sich innerhalb der Haupt Plugin Datei in einer Klasse befinden.

PHP Verzeichnis Übergabe prüfen

Ich muss in meinem Plugin für WordPress den ABSPATH übergeben, um eine eigene Ajax Behandlung zu haben.
Was meint ihr ist der Codeschnipsel dafür geeignet, um es möglicht sicher gegen Angriffe zu machen?

<?php
if ( is_file( dirname( dirname( dirname( dirname( __FILE__ ) ) ) ) . '/wp-load.php' ) ) {
	require_once( dirname( dirname( dirname( dirname( __FILE__ ) ) ) ) . '/wp-load.php' );
} else {
	$abspath = filter_input( INPUT_POST, 'ABSPATH', FILTER_SANITIZE_URL );
	$abspath = rtrim( realpath( $abspath ), '/' );
	if ( ! empty( $abspath ) && is_dir( $abspath . '/' ) && is_file( realpath( $abspath . '/wp-load.php' ) ) ) {
		require_once( $abspath . '/wp-load.php' );
	} else {
		die();
	}
}

Erläuterung:
Wenn der Plugins Ordner im Standard Verzeichnis ist oder zumindest in der selben Verzeichnis Tiefe muss die Übergabe nicht genutzt werden.
Sonst.
Das übergebene Verzeichnis vorfiltern (nur in URLs erlaubte Zeichen werden zugelassen)
mit ‚realpath()‘ alle ‚../‘,‘./‘ entfernen und prüfen, ob das Verzeichnis existiert.
Da ‚realpath()‘ auch das aktuelle Verzeichnis ausgibt nochmal Verzeichnis und Datei auf Existenz prüfen.
WP-load.php laden.

Ressourcen sparen bei Ajax Calls in WordPress

Bei meiner Arbeit am Plugin BackWPup habe ich nach einer Möglichkeit gesucht Ressourcen bei Ajax Calls und bei der Auftragsausführung zu sparen. Die einzige große Einsparung, die ich bisher gefunden habe, ist es die Übersetzungen anderer Plugins nicht mit zu laden, da die enorm viel Speicher verbrauchen. Dies bringt in meiner Testinstallation mit 20 Plugins eine Einsparung von 31 MB auf 25,5 MB Script Speicher. Da die Dateien auch nicht geöffnet werden, wird das auch noch eine Einsparung bringen, die ich im Moment nicht beziffern kann.

Hier die Umsetzung:
Wichtig ist hierbei, dass ich nur die Übersetzungen nicht lade, wenn es sich um Calls meines Plugins handelt.

<?php
define( 'PLUGIN_MENU_PAGES', 'page1,page2' );
if ( defined( 'DOING_AJAX' ) and DOING_AJAX and in_array(
		$_POST[ 'backwpupajaxpage' ], explode( ',', PLUGIN_MENU_PAGES )
	)
) {
	add_filter(
		'override_load_textdomain', create_function(
			'$default, $domain, $mofile', 'if ($domain=="textdomain") return $default; else return true;'
		), 1, 3
	);
}

Zusätzlich musste ich noch einbauen, dass mein Plugin als erstes geladen wird:

<?php
define( 'PLGUNINNAME_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );

public function pluginname_first_plugin( $newvalue, $oldvalue ) {

	if ( ! is_array( $newvalue ) ) {
		return $newvalue;
	}
	for ( $i = 0; $i < count( $newvalue ); $i++ ) {
		if ( $newvalue[ $i ] == PLGUNINNAME_PLUGIN_BASENAME ) {
			unset( $newvalue[ $i ] );
		}
	}
	array_unshift( $newvalue, PLGUNINNAME_PLUGIN_BASENAME );

	return $newvalue;
}

add_filter( 'pre_update_option_active_plugins', 'pluginname_first_plugin', 1, 2 );

Vielleicht kennt ja noch jemand eine Lösung die Ressourcen weiter zu optimieren und die WordPress eigene Ajax Behandlung zu nutzen…

Update:
mit einer etwas geänderten Funktion ist es nicht mehr notwendig das Plugin nach vorne zu schieben.

<?php
define( 'PLUGIN_MENU_PAGES', 'page1,page2' );
function overide_textdomain( $default, $domain, $mofile ) {

	if ( ( defined( 'DOING_CRON' ) && DOING_CRON )
		&& in_array(
			$_POST[ 'backwpupajaxpage' ], explode( ',', PLUGIN_MENU_PAGES )
		)
	) {
		global $l10n;
		if ( $domain == 'owntextdomainname' ) {
			foreach ( array_keys( $l10n ) as $domainkey ) {
				unset( $l10n[ $domainkey ] );
			}
		} else {
			return TRUE;
		}
	}

	return $default;
}

add_filter( 'override_load_textdomain', 'overide_textdomain' );

Update: Ich glaub das beste ist es, wenn in WordPress der WP-Performance-Gettext-Patch integriert wird. Nach meinen Tests bringt das am meisten. Der Speicherverbrauch geht dann auf ca. 17MB runter.