Existe uma maneira de usar os usuários do Wordpress, mas sem carregar todo o núcleo do Wordpress?


11

Eu tenho um site Wordpress e um aplicativo da Web que pode ser usado apenas pelos usuários registrados (Wordpress).

Agora estou carregando wp-blog-header.phppara verificar se o usuário está logado. Tudo está funcionando bem, mas porque a cada solicitação (incluindo AJAX) eu tenho que carregar também o núcleo do Wordpress, isso torna meu aplicativo lento visivelmente (mais de 70% do total tempo de carregamento).

Existe alguma maneira simples de usar os usuários do Wordpress, mas sem carregar todo o núcleo do Wordpress?

Atualização: preciso saber qual usuário está logado e também a segurança é importante.

Obrigado!

Respostas:


9

Se eu tivesse que fazer isso, usaria meu próprio cookie para determinar o login e carregaria apenas o WordPress para verificar quando necessário.

O cookie wordpress_logged_in_ {some-hash} pode ser usado para determinar o usuário, e o WordPress usa para determinar o mesmo. Você não pode reimplementar isso facilmente, mas pode usá-lo sem carregar o WordPress em várias solicitações.

Por exemplo, aqui está o meu hash de cookie (dados completamente compostos, mas realistas):

key: wordpress_logged_in_1234567890abcdef1234567890abcdef
value: admin|1234567890|abcdef1234567890abcdef1234567890

A maneira como o WordPress sabe como esse cookie é válido é irrelevante, tudo o que você precisa saber é se é válido uma vez e depois assina-o com um segredo.

Então, pela primeira vez, o usuário ainda não está comprovado. Você carrega o wp-load.php e o WP valida o cookie e efetua login no usuário. Agora você faz o que faz para provar a si mesmo que o usuário está logado e, em seguida, define seu próprio cookie. A chave pode ser qualquer coisa personalizada para você, o valor que você cria em um resumo da mensagem com uma chave secreta usando a função 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' );

Você receberá respostas sem sentido, que serão enviadas usando setcookie (). Em solicitações futuras, eles enviarão esse cookie de volta para você. Você pode verificar isso primeiro e validá-lo usando a mesma função hash e chave secreta.

Somente você pode gerar o hash porque somente você conhece a chave secreta. Portanto, se eles enviarem de volta um hash válido que também corresponda ao que eles enviam para o cookie WP, você saberá que eles foram validados com o WP, por meio do seu código, antes, e poderá obter o nome de usuário com esse valor (é o primeiro parte do cookie, obviamente). Então você não precisa carregar o WP.

A chave secreta, BTW, deve ser longa e aleatória . Não é uma senha curta. Não é uma palavra do dicionário. Apenas grandes bobagens absurdas. Ruído de linha e muito. Chave de exemplo: 'GHY5hFNqq4Ntdu=3:SUp8#/+_W!- @@^@xslN*L|N+Vn;(1xo8jNyp,au$v9Ki5*'


4

Como também estou usando algumas funções do Wordpress ao lado do gerenciamento de usuários, decidi continuar carregando o núcleo do WP, mas criei um arquivo personalizado que carrega apenas o que eu preciso e sem carregar os plugins. O novo tempo de carregamento é satisfatório (diminuiu de 1,5s na carga total do WP para 0,3s)

Criei um arquivo chamado 'wp-load-minimum.php' e chamo esse arquivo em vez de 'wp-blog-header.php'

Isso está funcionando para o WP 3.3. Aqui está o conteúdo do arquivo, se você achar que é útil:

<?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
Essa é uma boa ideia. Uma sugestão: você provavelmente pode abandonar o carregamento de plug-ins e configurar a consulta (dependendo do seu caso de uso, é claro).
Chrisguitarguy #

3

Para o Wordpress 4.9: Como não posso comentar (novo usuário). A alma final (instalação única do WP) que eu uso para fazer is_user_logged_in()e current_user_can()trabalhar é a seguinte. Nós require('wp-load.php') primeiro (para pular wp () na carga-blog-header.php) , e obter ABSPATHconstante, então, inclui manualmente exatamente todo o material necessário.

O uso do define('SHORTINIT', true)+ require('wp-load.php')+ manualmente inclui:

Carregamento de página: 1,05 sek - arquivos incluídos: 43 arquivos

Comparando: Usando SOMENTE require('wp-load.php') :

Carregamento de página: 1,35 sek - arquivos incluídos: 419 arquivos

A diferença de horário (0,3 sek) pode diferir das instalações e dos mecanismos PHP, mas, ao validar muitas solicitações em um carregamento de página, aumenta-se!

Lembre-se de usar a chamada relativa ao diretório instalado do WP. Em um diretório de plug-in personalizado do Wordpress, dentro de um nível de subdiretação, instalação normal, um caminho deve ser como:

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

Então:

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

Depois disso, a validação do usuário está acessível. Para outras tarefas, executando uma ou duas solicitações , rastrear outros arquivos necessários pode não valer 0,3 segundos. Pule a SHORTINITdesordem constante e manualmente.


+1 para usar a primeira chamada como relativa, as coisas podem ser muito complicadas se você emprestar o núcleo wp a partir de URLs absolutas.
Jonas Lundman

2

O próprio Wordpress está ativado ou desativado. Às vezes, mas isso é apenas por acaso e não por design, você pode contornar isso. Mas no seu caso, não tenho muita certeza se é possível.

Em vez de wp-blog-header.phpvocê pode tentar carregar apenas as funções WP, inclua wp-load.php. Talvez isso ajude.


wp-blog-header.phpbasicamente cargas wp-load.phppor isso não há diffrence ...

2
@ Victor: Há uma diferença. Poupa a inicialização do wp();que é realmente muito caro.
hakre 12/09/11

OK, agora estou tentando descobrir o que exatamente o wp () faz.

Eu fiz alguns testes com, em wp-load.phpvez de wp-blog-header.php, tudo parece funcionar bem, mas o tempo de carregamento é o mesmo.

@ Victor: Você está usando o relógio enquanto pressiona F5 ou como realmente mede? :) De qualquer forma, não use o WordPress se você realmente precisa de uma estrutura. Você pode tentar carregar apenas as funções que você realmente precisa. Mas você precisa procurá-los pouco a pouco. Basta incluir os arquivos que você realmente precisa, como funções do usuário e provavelmente o acesso ao banco de dados.
hakre 12/09/11

1

Você pode tentar acessar a tabela diretamente. Se você conhece o sal dos arquivos de senhas, pode fazê-los fazer login através do seu próprio sistema, salte a senha você mesmo (veja como o wordpress faz isso) e acompanhe você mesmo. Se você deseja navegar entre o seu próprio sistema e o wordpress sem re-autenticação, você pode criar um plugin para o wordpress que transmita a sessão atual dos usuários ao seu sistema.


0

O mais rápido que você pode obter com o WP é criar um invólucro personalizado que definirá SHORTINITe depois carregará o núcleo. Isso fará com que o carregamento principal pare logo após o banco de dados ser conectado e antes que a maioria das APIs e extensões (tema e plug-ins) sejam processadas.

A partir daí, você pode tentar acessar o banco de dados sozinho ou carregar seletivamente partes do núcleo necessárias.

Essa é uma abordagem bastante confusa, mas é tão próxima da carga do núcleo mais leve quanto as coisas acontecem no WP.


O SHORTINIT é uma boa abordagem, mas isso significa que todas as funções de verificação de usuários e hashes não serão carregadas. Você poderia reimplementar isso, mas confuso, como você disse.
Otto

@Otto Provavelmente não reimplementar, mas carregar as partes do núcleo manualmente. E se houver alguma modificação nos usuários, os plug-ins também serão carregados manualmente. Sim, esta é uma abordagem bastante envolvida. Mas a próxima alternativa para obter melhor desempenho é abandonar o WP inteiramente e trabalhar diretamente com o banco de dados, o que é ainda mais complicado.
Rarst


-1

Se você quiser permitir que todos os usuários do Wordpress usem o aplicativo da Web, use o sistema de gerenciamento de usuários do Wordpress e verifique se o usuário está logado ou não.

Para verificar isso, você precisará verificar se o cookie nomeado wordpress_logged_in_{some-hash}está presente. Caso contrário, redirecione o usuário para a página de login do Wordpress. A {some-hash}parte do nome do cookie é apenas uma série de letras e dígitos.


1
Preciso saber qual usuário está logado e também a segurança é importante.

Este é um pesadelo de segurança. Qualquer pessoa pode enviar uma solicitação com um cookie estruturado dessa maneira. Como você não está verificando o hash, mas apenas verificando se existe algo, isso equivale a um formulário de login, no qual você pode inserir qualquer coisa para usuário e senha, desde que os campos não estejam vazios.
Kraftner 15/09/16
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.