Existe-t-il un moyen d'utiliser les utilisateurs Wordpress mais sans charger l'intégralité du noyau Wordpress?

11

J'ai un site Wordpress et une application Web qui ne peuvent être utilisés que par les utilisateurs enregistrés (Wordpress).

Maintenant, je charge wp-blog-header.phppour vérifier si l'utilisateur est connecté. Tout fonctionne bien mais parce qu'à chaque demande (y compris AJAX) je dois également charger le noyau Wordpress, cela ralentit visiblement mon application (plus de 70% du total) temps de chargement).

Existe-t-il un moyen simple d'utiliser les utilisateurs de Wordpress mais sans charger l'intégralité du noyau Wordpress?

Mise à jour: J'ai besoin de savoir quel utilisateur est connecté et la sécurité est également importante.

Je vous remercie!

Victor
la source

Réponses:

9

Si je devais le faire, j'utiliserais mon propre cookie pour déterminer la connexion et ne chargerais WordPress que pour vérifier si nécessaire.

Le cookie wordpress_logged_in_ {some-hash} peut être utilisé pour déterminer l'utilisateur, et WordPress l'utilise pour le déterminer. Vous ne pouvez pas facilement réimplémenter cela, mais vous pouvez l'utiliser sans charger WordPress sur plusieurs demandes.

Par exemple, voici mon hachage de cookie (données entièrement constituées, mais réalistes):

key: wordpress_logged_in_1234567890abcdef1234567890abcdef
value: admin|1234567890|abcdef1234567890abcdef1234567890

La façon dont WordPress sait comment ce cookie est valide n'est pas pertinente, tout ce que vous devez savoir est de savoir s'il est valide une fois, puis vous le signez avec un secret.

Donc, la première fois, l'utilisateur n'a pas encore fait ses preuves. Vous chargez wp-load.php et WP valide le cookie et connecte l'utilisateur. Vous faites maintenant tout ce que vous faites pour vous prouver que l'utilisateur a été connecté, puis vous définissez votre propre cookie. La clé peut être quelque chose de personnalisé pour vous, la valeur que vous faites dans un résumé de message avec une clé secrète en utilisant la fonction hash_hmac.

$key = ... // the key from the WP cookie
$value = ... // the value from the WP cookie
$hash = hash_hmac ( 'md5' , $key.$value , 'some secret key' );

Vous récupérerez du charabia, que vous leur renvoyez en utilisant setcookie (). Lors de futures demandes, ils vous renverront ce cookie. Vous pouvez d'abord vérifier cela et le valider en utilisant la même fonction de hachage et la même clé secrète.

Vous seul pouvez générer le hachage car vous seul connaissez la clé secrète. Donc, s'ils renvoient un hachage valide qui correspond également à ce qu'ils envoient pour leur cookie WP, vous savez qu'ils ont déjà été validés avec WP, via votre code, et vous pouvez obtenir le nom d'utilisateur directement à partir de cette valeur (c'est le premier partie du cookie, évidemment). Ensuite, vous n'avez pas à charger WP.

La clé secrète, BTW, doit être longue et aléatoire . Pas un mot de passe court. Pas un mot du dictionnaire. Juste un gros charabia absurde. Du bruit de ligne, et beaucoup. Exemple de clé: 'GHY5hFNqq4Ntdu=3:SUp8#/+_W!- @@^@xslN*L|N+Vn;(1xo8jNyp,au$v9Ki5*'

Otto
la source
4

Parce que j'utilise également certaines fonctions Wordpress à côté de la gestion des utilisateurs, j'ai décidé de continuer à charger le noyau WP mais j'ai créé un fichier personnalisé qui ne charge que ce dont j'ai besoin et sans charger les plugins. Le nouveau temps de chargement est satisfaisant (il est passé de 1,5 s en pleine charge WP à 0,3 s)

J'ai créé un fichier appelé 'wp-load-minimum.php' et j'appelle ce fichier au lieu de 'wp-blog-header.php'

Ceci est inquiétant pour WP 3.3. Voici le contenu du fichier, si vous le trouvez utile:

<?php

//this stops wp-settings from load everything
define ('SHORTINIT',true);

error_reporting( E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_ERROR | E_WARNING | E_PARSE | E_USER_ERROR | E_USER_WARNING | E_RECOVERABLE_ERROR );

/** Define ABSPATH as this files directory */
define( 'ABSPATH', dirname(__FILE__) . '/' );

//WP config file
require ('wp-config.php');

if (SHORTINIT):

// Load the l18n library.
require( ABSPATH . WPINC . '/l10n.php' );

// Run the installer if WordPress is not installed.
wp_not_installed();


// Load most of WordPress.
require( ABSPATH . WPINC . '/class-wp-walker.php' );
//require( ABSPATH . WPINC . '/class-wp-ajax-response.php' );
require( ABSPATH . WPINC . '/formatting.php' );
require( ABSPATH . WPINC . '/capabilities.php' );
require( ABSPATH . WPINC . '/query.php' );
require( ABSPATH . WPINC . '/theme.php' );
require( ABSPATH . WPINC . '/user.php' );
require( ABSPATH . WPINC . '/meta.php' );
require( ABSPATH . WPINC . '/general-template.php' );
require( ABSPATH . WPINC . '/link-template.php' );
//require( ABSPATH . WPINC . '/author-template.php' );
require( ABSPATH . WPINC . '/post.php' );
//require( ABSPATH . WPINC . '/post-template.php' );
//require( ABSPATH . WPINC . '/category.php' );
//require( ABSPATH . WPINC . '/category-template.php' );
require( ABSPATH . WPINC . '/comment.php' );
//require( ABSPATH . WPINC . '/comment-template.php' );
require( ABSPATH . WPINC . '/rewrite.php' );
//require( ABSPATH . WPINC . '/feed.php' );
//require( ABSPATH . WPINC . '/bookmark.php' );
//require( ABSPATH . WPINC . '/bookmark-template.php' );
require( ABSPATH . WPINC . '/kses.php' );
require( ABSPATH . WPINC . '/cron.php' );
//require( ABSPATH . WPINC . '/deprecated.php' );
require( ABSPATH . WPINC . '/script-loader.php' );
require( ABSPATH . WPINC . '/taxonomy.php' );
//require( ABSPATH . WPINC . '/update.php' );
//require( ABSPATH . WPINC . '/canonical.php' );
require( ABSPATH . WPINC . '/shortcodes.php' );
require( ABSPATH . WPINC . '/media.php' );
require( ABSPATH . WPINC . '/http.php' );
require( ABSPATH . WPINC . '/class-http.php' );
require( ABSPATH . WPINC . '/widgets.php' );
require( ABSPATH . WPINC . '/nav-menu.php' );
//require( ABSPATH . WPINC . '/nav-menu-template.php' );
//require( ABSPATH . WPINC . '/admin-bar.php' );

// Load multisite-specific files.
if ( is_multisite() ) {
    require( ABSPATH . WPINC . '/ms-functions.php' );
    require( ABSPATH . WPINC . '/ms-default-filters.php' );
    require( ABSPATH . WPINC . '/ms-deprecated.php' );
}

// Define constants that rely on the API to obtain the default value.
// Define must-use plugin directory constants, which may be overridden in the sunrise.php drop-in.
wp_plugin_directory_constants( );

// Load must-use plugins.
/*foreach ( wp_get_mu_plugins() as $mu_plugin ) {
    include_once( $mu_plugin );
}
unset( $mu_plugin );*/

// Load network activated plugins.
if ( is_multisite() ) {
    foreach( wp_get_active_network_plugins() as $network_plugin ) {
        include_once( $network_plugin );
    }
    unset( $network_plugin );
}

do_action( 'muplugins_loaded' );

if ( is_multisite() )
    ms_cookie_constants(  );

// Define constants after multisite is loaded. Cookie-related constants may be overridden in ms_network_cookies().
wp_cookie_constants( );

// Define and enforce our SSL constants
wp_ssl_constants( );

// Create common globals.
require( ABSPATH . WPINC . '/vars.php' );

// Make taxonomies and posts available to plugins and themes.
// @plugin authors: warning: these get registered again on the init hook.
create_initial_taxonomies();
create_initial_post_types();

// Register the default theme directory root
//register_theme_directory( get_theme_root() );

// Load active plugins.
/*foreach ( wp_get_active_and_valid_plugins() as $plugin )
    include_once( $plugin );
unset( $plugin );*/

// Load pluggable functions.
require( ABSPATH . WPINC . '/pluggable.php' );
//require( ABSPATH . WPINC . '/pluggable-deprecated.php' );

// Set internal encoding.
wp_set_internal_encoding();

// Run wp_cache_postload() if object cache is enabled and the function exists.
if ( WP_CACHE && function_exists( 'wp_cache_postload' ) )
    wp_cache_postload();

do_action( 'plugins_loaded' );

// Define constants which affect functionality if not already defined.
wp_functionality_constants( );

// Add magic quotes and set up $_REQUEST ( $_GET + $_POST )
wp_magic_quotes();

do_action( 'sanitize_comment_cookies' );

/**
 * WordPress Query object
 * @global object $wp_the_query
 * @since 2.0.0
 */
$wp_the_query = new WP_Query();

/**
 * Holds the reference to @see $wp_the_query
 * Use this global for WordPress queries
 * @global object $wp_query
 * @since 1.5.0
 */
$wp_query =& $wp_the_query;

/**
 * Holds the WordPress Rewrite object for creating pretty URLs
 * @global object $wp_rewrite
 * @since 1.5.0
 */
$wp_rewrite = new WP_Rewrite();

/**
 * WordPress Object
 * @global object $wp
 * @since 2.0.0
 */
$wp = new WP();

/**
 * WordPress Widget Factory Object
 * @global object $wp_widget_factory
 * @since 2.8.0
 */
$GLOBALS['wp_widget_factory'] = new WP_Widget_Factory();

do_action( 'setup_theme' );

// Define the template related constants.
wp_templating_constants(  );

// Load the default text localization domain.
load_default_textdomain();

// Find the blog locale.
$locale = get_locale();
$locale_file = WP_LANG_DIR . "/$locale.php";
if ( ( 0 === validate_file( $locale ) ) && is_readable( $locale_file ) )
    require( $locale_file );
unset($locale_file);

// Pull in locale data after loading text domain.
require( ABSPATH . WPINC . '/locale.php' );

/**
 * WordPress Locale object for loading locale domain date and various strings.
 * @global object $wp_locale
 * @since 2.1.0
 */
$GLOBALS['wp_locale'] = new WP_Locale();

// Load the functions for the active theme, for both parent and child theme if applicable.
/*if ( ! defined( 'WP_INSTALLING' ) || 'wp-activate.php' === $pagenow ) {
    if ( TEMPLATEPATH !== STYLESHEETPATH && file_exists( STYLESHEETPATH . '/functions.php' ) )
        include( STYLESHEETPATH . '/functions.php' );
    if ( file_exists( TEMPLATEPATH . '/functions.php' ) )
        include( TEMPLATEPATH . '/functions.php' );
}*/

do_action( 'after_setup_theme' );

// Load any template functions the theme supports.
//require_if_theme_supports( 'post-thumbnails', ABSPATH . WPINC . '/post-thumbnail-template.php' );

// Set up current user.
$wp->init();

/**
 * Most of WP is loaded at this stage, and the user is authenticated. WP continues
 * to load on the init hook that follows (e.g. widgets), and many plugins instantiate
 * themselves on it for all sorts of reasons (e.g. they need a user, a taxonomy, etc.).
 *
 * If you wish to plug an action once WP is loaded, use the wp_loaded hook below.
 */
do_action( 'init' );

// Check site status
if ( is_multisite() ) {
    if ( true !== ( $file = ms_site_check() ) ) {
        require( $file );
        die();
    }
    unset($file);
}

/**
 * This hook is fired once WP, all plugins, and the theme are fully loaded and instantiated.
 *
 * AJAX requests should use wp-admin/admin-ajax.php. admin-ajax.php can handle requests for
 * users not logged in.
 *
 * @link http://codex.wordpress.org/AJAX_in_Plugins
 *
 * @since 3.0.0
 */
do_action('wp_loaded');

endif;

//require( ABSPATH . WPINC . '/pluggable.php' );
Victor
la source
1
C'est une bonne idée. Une suggestion: vous pouvez probablement abandonner le chargement du plugin et la configuration de la requête (en fonction de votre cas d'utilisation, bien sûr).
chrisguitarguy
3

Pour Wordpress 4.9: Comme je ne peux pas commenter (nouvel utilisateur). La soultion finale (installation WP unique) que j'utilise pour la création is_user_logged_in()et le current_user_can()travail, est la suivante. Nous commençons d' require('wp-load.php') abord (pour sauter wp () dans load-blog-header.php) , et obtenons ABSPATHensuite une constante, en incluant manuellement exactement tout le nécessaire.

L'utilisation manuelle de define('SHORTINIT', true)+ require('wp-load.php')+ comprend:

Pageload: 1.05 sek - fichiers inclus: 43 fichiers

Comparer: en utilisant UNIQUEMENT require('wp-load.php') :

Pageload: 1.35 sek - fichiers inclus: 419 fichiers

La différence de temps (0,3 sek) peut différer des installations et des moteurs PHP, mais tout en validant de nombreuses demandes sur un seul chargement de page, cela s'ajoute!

N'oubliez pas d'utiliser l'appel relatif au répertoire installé WP. À partir d'un répertoire de plug-in personnalisé Wordpress, à l'intérieur d'un niveau de sous-répertoire, installation normale, un chemin doit être comme:

$wordpress = '../../../../wp-load.php';

Puis:

define('SHORTINIT', true);
include_once $wordpress;

require_once ( ABSPATH . WPINC . '/class-wp-user.php' );
require_once ( ABSPATH . WPINC . '/class-wp-roles.php' );
require_once ( ABSPATH . WPINC . '/class-wp-role.php' );
require_once ( ABSPATH . WPINC . '/class-wp-session-tokens.php' );
require_once ( ABSPATH . WPINC . '/class-wp-user-meta-session-tokens.php' );
require_once ( ABSPATH . WPINC . '/formatting.php' );
require_once ( ABSPATH . WPINC . '/capabilities.php' );
//require_once ( ABSPATH . WPINC . '/query.php' ); // - might be useful
require_once ( ABSPATH . WPINC . '/user.php' );
require_once ( ABSPATH . WPINC . '/meta.php' );

wp_cookie_constants();

require_once ( ABSPATH . WPINC . '/vars.php' );
require_once ( ABSPATH . WPINC . '/kses.php' );
require_once ( ABSPATH . WPINC . '/rest-api.php' );
require_once ( ABSPATH . WPINC . '/pluggable.php' );

Après cela, la validation de l'utilisateur est accessible. Pour une autre tâche, rning sur une ou deux demandes , la recherche d'autres fichiers nécessaires peut ne pas valoir 0,3 sek. Sautez l' SHORTINITencombrement constant et manuel.

Anna Ericson
la source
+1 pour utiliser le premier appel comme parent, les choses pourraient être très compliquées si vous prêtiez le noyau wp à partir d'URL absolues.
Jonas Lundman
2

Wordpress lui-même est uniquement activé ou désactivé. Parfois, mais ce n'est que par hasard et non par conception, vous pouvez contourner cela. Mais dans votre cas, je ne sais pas vraiment si c'est possible.

Au lieu de wp-blog-header.phpvous pouvez essayer de ne charger que les fonctions WP, incluez wp-load.phpplutôt. Peut-être que cela aide.

hakre
la source
wp-blog-header.phpcharge essentiellement wp-load.phpdonc il n'y a pas de différence ...
2
@Victor: Il y a une différence. Il épargne la mise en route wp();qui est en fait assez chère.
hakre
OK, maintenant j'essaie de comprendre ce que fait exactement wp ().
J'ai fait un test avec wp-load.phpau lieu de wp-blog-header.php, tout semble bien fonctionner mais le temps de chargement est le même.
@Victor: Utilisez-vous votre montre tout en appuyant sur F5 ou comment mesurez-vous réellement? :) Quoi qu'il en soit, n'utilisez pas WordPress si vous avez réellement besoin d'un framework. Vous pouvez essayer de charger uniquement les fonctions dont vous avez réellement besoin à la place. Mais vous devez les rechercher petit à petit. Incluez simplement les fichiers dont vous avez réellement besoin, comme pour les fonctions utilisateur et l'accès à la base de données probablement.
hakre
1

Vous pouvez essayer d'accéder directement à la table. Si vous connaissez le sel des fichiers de mot de passe, vous pouvez les faire vous connecter via votre propre système, salez le mot de passe vous-même (regardez comment wordpress le fait) et gardez une trace d'eux. Si vous souhaitez pouvoir passer de votre propre système à wordpress sans réauthentification, vous pouvez créer un plugin pour wordpress qui transmet la session des utilisateurs en cours à votre système.


la source
0

Le plus rapide que vous pouvez obtenir avec WP est de créer un wrapper personnalisé qui définira SHORTINITpuis chargera le noyau. Cela entraînera l'arrêt de la charge principale juste après la connexion de la base de données et avant le traitement de la plupart des API et extensions (thème et plug-ins).

De là, vous pouvez essayer d'obtenir uniquement par base de données ou charger de manière sélective les parties du noyau dont vous avez besoin.

C'est une approche assez compliquée, mais elle est aussi proche d'une charge de base plus légère que les choses dans WP.

Rarst
la source
SHORTINIT est une bonne approche, mais cela signifie que toutes les fonctions de vérification des utilisateurs et des hachages et autres ne seront pas chargées. Vous pourriez réimplémenter cela, mais en désordre, comme vous l'avez dit.
Otto
@Otto Probablement pas réimplémentation, mais chargez plutôt ces parties de noyau à la main. Et si des modifications sont apportées aux utilisateurs par des plugins, chargez-les également à la main. Oui, c'est une approche assez complexe. Mais la prochaine alternative pour de meilleures performances est d'abandonner complètement WP et de travailler directement avec la base de données, ce qui est encore plus compliqué.
Rarst
-1

Si vous souhaitez simplement autoriser tous les utilisateurs de Wordpress à utiliser l'application Web, vous pouvez utiliser le système de gestion des utilisateurs de Wordpress et vérifier simplement si l'utilisateur est connecté ou non.

Pour vérifier cela, vous devrez vérifier si le cookie nommé wordpress_logged_in_{some-hash}est présent. Sinon, redirigez l'utilisateur vers la page de connexion de Wordpress. La {some-hash}partie du nom du cookie n'est qu'une série de lettres et de chiffres.


la source
1
J'ai besoin de savoir quel utilisateur est connecté et la sécurité est également importante.
C'est un cauchemar pour la sécurité. Tout le monde peut envoyer une demande avec un cookie structuré comme ceci. Comme vous ne vérifiez pas le hachage mais vérifiez simplement s'il y a quelque chose, cela équivaut à un formulaire de connexion où vous pouvez entrer n'importe quoi pour l'utilisateur et le mot de passe tant que les champs ne sont pas vides.
kraftner