web-dev-qa-db-fra.com

Problème Wordpress Nonce pour la connexion et la déconnexion Ajax

J'utilise ajax pour soumettre les informations d'identification de connexion et de déconnexion. Les formulaires de connexion et de déconnexion sont remplacés par le code HTML renvoyé par une réponse réussie. Aucun chargement de page ne se produit Le contenu de la page n'est chargé via une demande ajax get après une connexion réussie ou une déconnexion réussie.

Je peux réussir à me connecter, puis à me déconnecter, mais lorsque je tente de me connecter une seconde fois, je reçois un échec de nonce (-1) de check_admin_referer (). J'ai vérifié que le nonce envoyé lors de la deuxième connexion était différent de celui de la première soumission, mais autant que je sache avec nonce. Ce nonce est renvoyé à la demande ajax lors du processus de déconnexion.

Ai-je trop réfléchi au besoin de rafraîchir ou de stocker quelque chose dans une session ou une variable globale? Mon code fonctionne lors de la première tentative de connexion et la déconnexion du partage de mon code n'est probablement pas bénéfique ici.

Quelqu'un at-il une idée de la raison pour laquelle le nonce que je reçois est invalide?

EDITS BELOW

S'il vous plaît voir mon code, c'est un mélange de php et javascript

<?php
/* the php sidebar menu for a logged in user
 * this is also fetched by the ajax log in action
 */
function not_logged_in_menu() { ?>

    <div class="login-form">
        <h2>Login</h2>

        <form method="post" action="<?php site_url(); ?>/wp-login.php" class="wp-user-form">
            <div class="input-login">
                <div class="loader"></div>
                <input type="submit" class="login ui-btn" name="Login" value="Login" />
                <span class="gzp-icon-login"></span>
            </div>
            <div class="input-prepend">
                <span class="add-on icon-username"></span>
                <input type="text" name="log" value="" class="input-medium" id="user_login" placeholder="Username" />
            </div>
            <?php /*<br class="clearer" />*/ ?>
            <div class="input-prepend">
                <span class="add-on icon-password"></span>
                <input type="password" name="pwd" value="" id="user_pass" class="input-medium" placeholder="Password" />
            </div>
            <?php wp_nonce_field( 'ajax-login-nonce', 'security' ); ?>                  
        </form>
    </div> <?php
}

/* the php sidebar menu for a logged out user
 * this is also fetched by the ajax log out action
 */
function logged_in_menu() {
        global $user_identity; ?>

    <div class="login-form">
        <h2 class="welcome">Welcome<br /><?php echo $user_identity; ?></h2>

        <a href="<?php echo wp_logout_url( home_url() ); ?>" id="logout" class="btn btn-inverse" title="Logout">Logout</a>
        <div class="loader"></div>
        <div class="clearer"></div>
    </div> <?php
}

/* the php login ajax action */
function ajax_login(){

        check_ajax_referer( 'ajax-login-nonce', 'security' ); // on the second log in attempt with no page refresh this
                                                              // function fails her

        // Nonce is checked, get the POST data and sign user on
        $info = array();
        $info['user_login'] = $_POST['username'];
        $info['user_password'] = $_POST['password'];
        $info['remember'] = true;

        $user = wp_signon( $info, false );

        if ( is_wp_error($user) ){
                echo json_encode(array('loggedin'=>false, 'message'=>__('Wrong username or password.')));
                die();
        }

        //setting the user variables so the globals have content without an actual page load
        wp_set_current_user( $user->ID, $user->user_login );
        wp_set_auth_cookie( $user->ID, true, false );
        do_action( 'wp_login', $user->user_login );

        ob_start();
        gzp_logged_in_menu();
        $menu_content = ob_get_contents();
        ob_end_clean();

        echo json_encode(array('loggedin'=>true, 'message'=>__('Login successful, redirecting...'), 'menu_content'=>$menu_content,'user_signon'=>$user));

        die();
}
add_action( 'wp_ajax_nopriv_ajaxlogin', 'ajax_login' );


/* the php log out ajax action */
function ajax_logout(){

        // First check the nonce, if it fails the function will break
        wp_verify_nonce( $_POST['security'], 'log-out' );

        wp_logout();

        ob_start();
        gzp_not_logged_in_menu();
        $menu_content = ob_get_contents();
        ob_end_clean();

        echo json_encode(array('loggedout'=>true, 'message'=>__('Logout successful, redirecting...'), 'menu_content'=>$menu_content));

        die();
}
add_action( 'wp_ajax_ajaxlogout', 'ajax_logout' );
?>


<script type="text/javascript">
/* javascripted loaded in the head of page on page load */
jQuery(document).ready(function(event) {
        admin_bar_login();
        admin_bar_logout();
});    
/* the ajax post for a log in attempt */
function admin_bar_login() {
        /* login action */
        jQuery('form.wp-user-form').on('submit', function(e) {
                e.preventDefault();

                jQuery('.login-form input.login').parent('.input-login').addClass('loading').show();
                console.log(jQuery('form.wp-user-form #security').val());
                jQuery.ajax({
                        type: 'POST',
                        dataType: 'json',
                        url: ajaxurl,
                        data: {
                                'action': 'ajaxlogin', //calls wp_ajax_nopriv_ajaxlogin
                                'username': jQuery('form.wp-user-form #user_login').val(),
                                'password': jQuery('form.wp-user-form #user_pass').val(),
                                'security': jQuery('form.wp-user-form #security').val()
                        },
                        success: function(data){
                                if (data.loggedin == true){
                                        jQuery('.navigation-right .menu').html(data.menu_content);
                                        AAPL_loadPage(document.location.toString(),1); //refresh the #content of the page
                                        admin_bar_logout(); //this adds the event handler to the log out content just added
                                        jQuery.bootstrapGrowl(data.message);
                                }
                                else if(data.loggedin == false) {
                                        jQuery('.login-form input.login').parent('.input-login').removeClass('loading');
                                        jQuery.bootstrapGrowl(data.message);
                                }
                        },
                        fail: function(data){
                                if(data.loggedin == 'false')
                                        jQuery.bootstrapGrowl(data.message);
                        }
                });                                            
        });
}
/* the ajax post for a log out attempt */
function admin_bar_logout() {
        //logout action
        jQuery('#logout').on('click', function(e) {
                e.preventDefault();

                jQuery(this).parent('.login-form').addClass('loading').show();
                var href = jQuery(this).attr('href'),
                    vars = href.split("&"),
                    wp_nonce = '_wpnonce',
                    security = '';

                for (var i=0;i<vars.length;i++) {
                           var pair = vars[i].split("=");
                           if(pair[0] == wp_nonce){security = pair[1];}
                }

                jQuery.ajax({
                        type: 'POST',
                        dataType: 'json',
                        url: ajaxurl,
                        data: {
                                'action': 'ajaxlogout', //calls wp_ajax_ajaxlogout
                                'security': security,
                        },
                        success: function(data){
                                if (data.loggedout == true){
                                        jQuery('.navigation-right .menu').html(data.menu_content);
                                        AAPL_loadPage(document.location.toString(),1); //refresh the #content of the page
                                        admin_bar_login(); //this adds the event handler to the log in content just added
                                        jQuery.bootstrapGrowl(data.message);
                                }
                                else if(data.loggedin == false) {
                                        jQuery('.login-form input.login').parent('.input-login').removeClass('loading');
                                        jQuery.bootstrapGrowl(data.message);
                                }
                        },
                        fail: function(data){
                                if(data.loggedin == 'false')
                                        jQuery.bootstrapGrowl(data.message);
                        }
                });                                            
        });
}
</script>

Solution ci-dessous

La réponse correcte pour mon problème était indiquée ci-dessous, mais j'avais également un autre problème, mon utilisateur n'étant pas déconnecté. Le nonce renvoyé était un nonce connecté. Lorsque j'ai essayé de me reconnecter en tant qu'utilisateur anonyme, le nonce n'était pas valide pour wp_verify_nonce().

J'ai constaté que le simple fait d'utiliser wp_logout() pour se déconnecter n'était pas suffisant dans mon cas. La variable $current_user a toujours conservé toutes les données utilisateur et is_user_logged_in() a renvoyé la valeur true. Ce n'était pas jusqu'à ce que je définisse wp_set_current_user(0) ai vu l'utilisateur a été déconnecté.

J'ai également supprimé la nécessité d'un nonce lors de la connexion.

Voir ce post pour discussion sur ce sujet

wp_logout Ne pas me déconnecter

2
stoi2m1

Je n'avais pas exécuté votre code, mais je suppose que la faute dans votre flux de code est que les nonces sont spécifiques à l'utilisateur. Bien que le nonce anonyme soit possible, il ne sert à rien car il serait identique pour les utilisateurs all anonymes.

Il y a donc probablement une discordance quelque part et vous essayez d'utiliser un nom d'utilisateur spécifique tout en restant anonyme.

1
Rarst

Une autre chose à considérer est que le système wp nonce utilise à la fois l'ID utilisateur actuel et le sessiontoken (cookie wordpress_logged_in _...).

Si vous regardez la source de la fonction wp_verify_nonce, vous verrez qu'il compare le nonce avec le hachage de (période actuelle et dernière de 12 heures + '|' + action + '|' + 'currentuser-id +' | '+ sessiontoken)

Toute modification de l'une de ces variables ferait que le hachage ne corresponde pas.

0
NoBugs