C'è un modo per usare gli utenti di Wordpress ma senza caricare l'intero core di Wordpress?


11

Ho un sito Wordpress e un'applicazione Web che può essere utilizzata solo dagli utenti registrati (Wordpress).

Ora sto caricando wp-blog-header.phpper verificare se l'utente ha effettuato l'accesso. Tutto funziona correttamente ma perché su ogni richiesta (incluso AJAX) devo caricare anche il core di Wordpress, rallenta visibilmente la mia applicazione (oltre il 70% dal totale tempo di caricamento).

Esiste un modo semplice per utilizzare gli utenti di Wordpress ma senza caricare l'intero core di Wordpress?

Aggiornamento: devo sapere quale utente ha effettuato l'accesso e anche la sicurezza è importante.

Grazie!

Risposte:


9

Se dovessi farlo, utilizzerei il mio cookie per determinare il login e caricare WordPress solo per controllare quando necessario.

Il cookie wordpress_logged_in_ {some-hash} può essere utilizzato per determinare l'utente e WordPress lo utilizza per determinare lo stesso. Non è possibile reimplementarlo facilmente, ma è possibile utilizzarlo senza caricare WordPress su più richieste.

Ad esempio, ecco il mio cookie hash (dati completamente inventati, ma realistico):

key: wordpress_logged_in_1234567890abcdef1234567890abcdef
value: admin|1234567890|abcdef1234567890abcdef1234567890

Il modo in cui WordPress sa quanto sia valido quel cookie è irrilevante, tutto ciò che devi sapere è se è valido una volta, quindi lo firmi con un segreto.

Quindi, la prima volta, l'utente non è ancora stato provato. Carichi wp-load.php e WP convalida il cookie e accede l'utente. Ora fai tutto ciò che fai per dimostrare a te stesso che l'utente è stato loggato, quindi imposti il ​​tuo cookie. La chiave può essere qualcosa di personalizzato per te, il valore che crei in un digest del messaggio con una chiave segreta usando la funzione 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' );

Tornerai senza parole, che rispedirai loro usando setcookie (). Su richieste future, ti rispediranno questo cookie. Puoi verificarlo prima e convalidarlo usando la stessa funzione hash e la chiave segreta.

Solo tu puoi generare l'hash perché solo tu conosci la chiave segreta. Quindi, se restituiscono un hash valido che corrisponde anche a quello che inviano per il loro cookie WP, allora sai che sono stati convalidati con WP, tramite il tuo codice, in precedenza, e puoi ottenere lo username proprio da quel valore (è il primo parte del cookie, ovviamente). Quindi non è necessario caricare WP.

La chiave segreta, a proposito, dovrebbe essere lunga e casuale . Non una password breve. Non una parola del dizionario. Solo grandi sciocchezze senza senso. Rumore di linea e molto altro. Chiave di esempio: 'GHY5hFNqq4Ntdu=3:SUp8#/+_W!- @@^@xslN*L|N+Vn;(1xo8jNyp,au$v9Ki5*'


4

Poiché sto anche utilizzando alcune funzioni di Wordpress accanto alla gestione degli utenti, ho deciso di continuare a caricare il core WP, ma ho creato un file personalizzato che carica solo ciò di cui ho bisogno e senza caricare i plugin. Il nuovo tempo di caricamento è soddisfacente (è diminuito da 1,5 secondi a pieno carico WP a 0,3 secondi)

Ho creato un file chiamato "wp-load-minimum.php" e lo chiamo invece di "wp-blog-header.php"

Questo è woking per WP 3.3. Ecco il contenuto del file, se lo trovi 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' );

1
Questa è una buona idea. Un suggerimento: probabilmente è possibile abbandonare il caricamento del plug-in e l'impostazione della query (a seconda del caso d'uso, ovviamente).
chrisguitarguy,

3

Per Wordpress 4.9: non posso commentare (nuovo utente). L'anima finale (singola installazione WP) che utilizzo per creare is_user_logged_in()e current_user_can()lavorare è la seguente. Abbiamo require('wp-load.php') prima (di saltare wp () del carico-blog-header.php) , e ottenere ABSPATHcostante allora, include manualmente esattamente tutte le cose necessarie.

L'uso di define('SHORTINIT', true)+ require('wp-load.php')+ include manualmente:

Pageload: 1.05 sek - file inclusi: 43 file

Confronto: utilizzando SOLO require('wp-load.php') :

Pageload: 1,35 sek - file inclusi: 419 file

La differenza di tempo (0.3 sek) potrebbe differire dalle installazioni e dai motori PHP, ma durante la convalida di molte richieste su un unico pageload, le cose si sommano!

Ricordarsi di utilizzare la chiamata relativa alla directory installata WP. Da una directory di plugin personalizzata di Wordpress, all'interno di un livello secondario, installazione normale, un percorso dovrebbe essere come:

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

Poi:

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' );

Successivamente, è possibile accedere alla convalida dell'utente. Per altre attività, in risposta a una o due richieste , rintracciare altri file necessari potrebbe non valere 0,3 sek. Salta la SHORTINITcostante e ingombra manualmente.


+1 per usare la prima chiamata come relativo, Le cose potrebbero essere davvero disordinate se si prestano core wp da url assoluti.
Jonas Lundman,

2

Wordpress stesso è solo attivato o disattivato. A volte, ma è solo per caso e non per progettazione, puoi aggirare quello. Ma nel tuo caso, non sono davvero sicuro che sia possibile.

Invece di wp-blog-header.phpprovare a caricare solo le funzioni WP, includi wp-load.phpinvece. Forse questo aiuta.


wp-blog-header.phpfondamentalmente carica wp-load.phpquindi non c'è differenza ...

2
@Victor: c'è una differenza. Risparmia il fuoco wp();che in realtà è piuttosto costoso.
Hacre,

OK, ora sto cercando di capire cosa fa esattamente wp ().

Ho fatto alcuni test wp-load.phpinvece di wp-blog-header.php, tutto sembra funzionare bene ma il tempo di caricamento è lo stesso.

@Victor: stai usando l'orologio mentre premi F5 o come misuri effettivamente? :) Comunque, non usare WordPress se in realtà hai bisogno di un framework. In alternativa, puoi provare a caricare solo le funzioni effettivamente richieste. Ma devi cercarli a poco a poco. Includi semplicemente i file di cui hai effettivamente bisogno, come probabilmente per le funzioni utente e l'accesso al database.
Hacre,

1

Potresti provare ad accedere direttamente alla tabella. Se conosci il salt dei file delle password puoi farli accedere tramite il tuo sistema, salare tu stesso la password (guarda come funziona wordpress) e tenerne traccia tu stesso. Se si desidera la possibilità di attraversare il proprio sistema e wordpress senza ripetere l'autenticazione, è possibile creare un plug-in per wordpress che passi la sessione corrente degli utenti al proprio sistema.


0

Il più veloce che puoi ottenere con WP è creare un wrapper personalizzato che definirà SHORTINITe quindi caricherà il core. Ciò interromperà il caricamento del core subito dopo la connessione del database e prima che la maggior parte delle API e delle estensioni (tema e plugin) vengano elaborate.

Da lì puoi provare a ottenere dal database da solo o caricare selettivamente parti del core di cui hai bisogno.

Questo è un approccio piuttosto disordinato, ma è vicino a un carico core più leggero di quanto le cose entrino in WP.


SHORTINIT è un buon approccio, ma ciò significa che tutte le funzioni per il controllo degli utenti, degli hash e simili non verranno caricate. Potresti reimplementarlo, ma disordinato, come hai detto.
Otto

@Otto Probabilmente non reimplementazione, ma piuttosto caricare manualmente quelle parti del core. E se ci sono modifiche agli utenti, i plugin caricano anche quelli manualmente. Sì, questo è un approccio abbastanza coinvolto. Ma la prossima alternativa per migliorare le prestazioni è abbandonare completamente WP e lavorare direttamente con il database, il che è ancora più disordinato.
Rarst


-1

Se si desidera solo consentire a tutti gli utenti di Wordpress di utilizzare l'app Web, è possibile utilizzare il sistema di gestione utenti di Wordpress e controllare semplicemente se l'utente ha effettuato l'accesso o meno.

Per verificare ciò dovrai verificare se wordpress_logged_in_{some-hash}è presente il cookie indicato . In caso contrario, reindirizzare l'utente alla pagina di accesso di Wordpress. La {some-hash}parte del nome del cookie è solo una serie di lettere e cifre.


1
Devo sapere quale utente ha effettuato l'accesso e anche la sicurezza è importante.

Questo è un incubo per la sicurezza. Chiunque può inviare una richiesta con un cookie strutturato in questo modo. Dato che non stai controllando l'hash, ma solo controllando se c'è qualcosa, questo equivale a un modulo di accesso in cui puoi inserire qualsiasi cosa per utente e password purché i campi non siano vuoti.
Kraftner,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.