प्रत्येक अजाक्स अनुरोध के लिए एक अद्वितीय गैर कैसे प्राप्त करें?


11

मैंने बाद में अजाक्स अनुरोधों के लिए एक अद्वितीय नॉनसेंस को पुन: उत्पन्न करने के लिए वर्डप्रेस प्राप्त करने के बारे में कुछ चर्चाएँ देखी हैं, लेकिन मेरे जीवन के लिए मुझे वास्तव में ऐसा करने के लिए वर्डप्रेस नहीं मिल सकता है - हर बार जब मैं सोचता हूं कि मुझे एक नया होना चाहिए गैर, मुझे Wordpress से वही नॉन बैक मिलता है। मैं WP के nonce_life की अवधारणा को समझता हूं और यहां तक ​​कि इसे किसी और चीज़ के लिए सेट कर रहा हूं, लेकिन इससे मुझे मदद नहीं मिली है।

मैं स्थानीयकरण के माध्यम से हेडर में JS ऑब्जेक्ट में नॉन जेनरेट नहीं करता- मैं इसे अपने डिस्प्ले पेज पर करता हूं। मैं अपने पेज को अजाक्स के अनुरोध को संसाधित करने के लिए प्राप्त कर सकता हूं, लेकिन जब मैं कॉलबैक में WP से एक नए नॉनसे का अनुरोध करता हूं, तो मुझे वही नॉन बैक मिलता है, और मुझे नहीं पता कि मैं क्या गलत कर रहा हूं ... आखिरकार मैं चाहता हूं इसे बढ़ाएं ताकि पृष्ठ पर कई आइटम हो सकें, प्रत्येक को जोड़ने / हटाने की क्षमता के साथ - इसलिए मुझे एक समाधान की आवश्यकता है जो एक पृष्ठ से कई बाद के अजाक्स अनुरोधों की अनुमति देगा।

(और मुझे यह कहना चाहिए कि मैंने इस कार्यक्षमता को एक प्लगइन में डाल दिया है, इसलिए फ्रंट-एंड "डिस्प्ले पेज" वास्तव में प्लगइन के साथ शामिल एक फ़ंक्शन है ...)

functions.php: स्थानीयकरण करें, लेकिन मैं यहां एक नॉनवेज नहीं बनाता

wp_localize_script('myjs', 'ajaxVars', array('ajaxurl' => 'admin-ajax.php')));

जेएस कॉलिंग:

$("#myelement").click(function(e) {
    e.preventDefault();
    post_id = $(this).data("data-post-id");
    user_id = $(this).data("data-user-id");
    nonce = $(this).data("data-nonce");
    $.ajax({
      type: "POST",
      dataType: "json",
      url: ajaxVars.ajaxurl,
      data: {
         action: "myfaves",
         post_id: post_id,
         user_id: user_id,
         nonce: nonce
      },
      success: function(response) {
         if(response.type == "success") {
            nonce = response.newNonce;
            ... other stuff
         }
      }
  });
});

PHP प्राप्त करना:

function myFaves() {
   $ajaxNonce = 'myplugin_myaction_nonce_' . $postID;
   if (!wp_verify_nonce($_POST['nonce'], $ajaxNonce))
      exit('Sorry!');

   // Get various POST vars and do some other stuff...

   // Prep JSON response & generate new, unique nonce
   $newNonce = wp_create_nonce('myplugin_myaction_nonce_' . $postID . '_' 
       . str_replace('.', '', gettimeofday(true)));
   $response['newNonce'] = $newNonce;

   // Also let the page process itself if there is no JS/Ajax capability
   } else {
      header("Location: " . $_SERVER["HTTP_REFERER"];
   }
   die();
}

फ़्रंटेंड PHP प्रदर्शन फ़ंक्शन, जिसके बीच में है:

$nonce = wp_create_nonce('myplugin_myaction_nonce_' . $post->ID);
$link = admin_url('admin-ajax.php?action=myfaves&post_id=' . $post->ID
   . '&user_id=' . $user_ID
   . '&nonce=' . $nonce);

echo '<a id="myelement" data-post-id="' . $post->ID
   . '" data-user-id="' . $user_ID
   . '" data-nonce="' . $nonce
   . '" href="' . $link . '">My Link</a>';

इस बिंदु पर मैं वास्तव में किसी भी सुराग या संकेत के लिए आभारी हूँ WP में प्रत्येक नए Ajax अनुरोध के लिए एक अद्वितीय nonce पुनर्जीवित करने के लिए ...


अद्यतन: मैंने अपनी समस्या हल कर ली है। ऊपर दिए गए कोड स्निपेट मान्य हैं, हालांकि मैंने PHP कॉलबैक में $ newNonce निर्माण को बदल दिया है ताकि यह सुनिश्चित हो सके कि बाद के अजाक्स अनुरोधों पर यह अद्वितीय है।


एक से बहुत संक्षिप्त देखो: आप अस्थायी रूप से बना रहे हैं के बाद आप इसे प्राप्त (प्रदर्शन पर)? आप इसे स्थानीयकरण कॉल के दौरान क्यों नहीं बना रहे हैं?
केसर

JQuery # myelement लिंक में "डेटा-नॉन" विशेषता से प्रारंभिक नॉन का उपयोग कर रहा है, और विचार यह है कि पृष्ठ को अजाक्स या स्वयं द्वारा संसाधित किया जा सकता है। मुझे ऐसा लग रहा था कि स्थानीय कॉल के माध्यम से एक बार नॉनस बनाने से यह गैर-जेएस प्रसंस्करण से बाहर हो जाएगा, लेकिन मैं इसके बारे में गलत हो सकता हूं। किसी भी तरह से Wordpress मुझे वही नॉन बैक देता है ...
टिम

इसके अलावा: स्थानीय कॉल में नॉनस को न डालें, एक को एक पेज पर कई आइटम होने से रोक सकते हैं, जहां प्रत्येक आइटम एक अजाक्स अनुरोध के लिए एक अनूठा नॉनस हो सकता है?
टिम

स्थानीयकरण के अंदर नॉनस क्रिएट करना और उस एक स्क्रिप्ट के लिए इसे उपलब्ध कराना। लेकिन आप अलग-अलग नॉनवेज के साथ असीमित मात्रा में अन्य (कुंजी नाम) का स्थानीयकरण जोड़ सकते हैं।
केसर

यदि आपने इसे हल कर लिया है तो आपको अपना उत्तर पोस्ट करने के लिए प्रोत्साहित किया जाता है और इसे "स्वीकार" किया जाता है। यह साइट को व्यवस्थित रखने में मदद करेगा। मैं सिर्फ आपके कोड के साथ गड़बड़ कर रहा था और कुछ चीजें मेरे लिए काम नहीं करती हैं, इसलिए आपके समाधान के लिए आपसे अनुरोध करने के लिए यह अनुरोध दोगुना है।
s_ha_dum

जवाबों:


6

यहाँ मेरे अपने प्रश्न का बहुत लंबा जवाब है जो बाद में अजाक्स अनुरोधों के लिए अद्वितीय गैर उत्पन्न करने के प्रश्न को संबोधित करने से परे है। यह एक "पसंदीदा में जोड़ें" सुविधा है जिसे उत्तर के प्रयोजनों के लिए सामान्य बनाया गया था (मेरी सुविधा उपयोगकर्ताओं को पसंदीदा की सूची में फोटो अटैचमेंट की पोस्ट आईडी को जोड़ने की सुविधा देती है, लेकिन यह कई अन्य सुविधाओं पर लागू हो सकता है जो भरोसा करते हैं अजाक्स)। मैंने इसे एक स्टैंडअलोन प्लगइन के रूप में कोडित किया है, और कुछ आइटम गायब हैं - लेकिन यह बहुत विस्तार से होना चाहिए यदि आप सुविधा को फिर से भरना चाहते हैं, तो यह प्रदान करने के लिए पर्याप्त विवरण होना चाहिए। यह एक अलग पोस्ट / पेज पर काम करेगा, लेकिन यह पोस्ट की सूचियों में भी काम करेगा (जैसे आप अजाक्स के माध्यम से पसंदीदा इनलाइन के लिए आइटम जोड़ सकते हैं / हटा सकते हैं और प्रत्येक पोस्ट में प्रत्येक Ajax अनुरोध के लिए अपना अनूठा नॉन होगा)। ध्यान रखें कि वहाँ '

scripts.php

/**
* Enqueue front-end jQuery
*/
function enqueueFavoritesJS()
{
    // Only show Favorites Ajax JS if user is logged in
    if (is_user_logged_in()) {
        wp_enqueue_script('favorites-js', MYPLUGIN_BASE_URL . 'js/favorites.js', array('jquery'));
        wp_localize_script('favorites-js', 'ajaxVars', array('ajaxurl' => admin_url('admin-ajax.php')));
    }
}
add_action('wp_enqueue_scripts', 'enqueueFavoritesJS');

पसंदीदा .js (बहुत सारे डिबग सामान जिन्हें हटाया जा सकता है)

$(document).ready(function()
{
    // Toggle item in Favorites
    $(".faves-link").click(function(e) {
        // Prevent self eval of requests and use Ajax instead
        e.preventDefault();
        var $this = $(this);
        console.log("Starting click event...");

        // Fetch initial variables from the page
        post_id = $this.attr("data-post-id");
        user_id = $this.attr("data-user-id");
        the_toggle = $this.attr("data-toggle");
        ajax_nonce = $this.attr("data-nonce");

        console.log("data-post-id: " + post_id);
        console.log("data-user-id: " + user_id);
        console.log("data-toggle: " + the_toggle);
        console.log("data-nonce: " + ajax_nonce);
        console.log("Starting Ajax...");

        $.ajax({
            type: "POST",
            dataType: "json",
            url: ajaxVars.ajaxurl,
            data: {
                // Send JSON back to PHP for eval
                action : "myFavorites",
                post_id: post_id,
                user_id: user_id,
                _ajax_nonce: ajax_nonce,
                the_toggle: the_toggle
            },
            beforeSend: function() {
                if (the_toggle == "y") {
                    $this.text("Removing from Favorites...");
                    console.log("Removing...");
                } else {
                    $this.text("Adding to Favorites...");
                    console.log("Adding...");
                }
            },
            success: function(response) {
                // Process JSON sent from PHP
                if(response.type == "success") {
                    console.log("Success!");
                    console.log("New nonce: " + response.newNonce);
                    console.log("New toggle: " + response.theToggle);
                    console.log("Message from PHP: " + response.message);
                    $this.text(response.message);
                    $this.attr("data-toggle", response.theToggle);
                    // Set new nonce
                    _ajax_nonce = response.newNonce;
                    console.log("_ajax_nonce is now: " + _ajax_nonce);
                } else {
                    console.log("Failed!");
                    console.log("New nonce: " + response.newNonce);
                    console.log("Message from PHP: " + response.message);
                    $this.parent().html("<p>" + response.message + "</p>");
                    _ajax_nonce = response.newNonce;
                    console.log("_ajax_nonce is now: " + _ajax_nonce);
                }
            },
            error: function(e, x, settings, exception) {
                // Generic debugging
                var errorMessage;
                var statusErrorMap = {
                    '400' : "Server understood request but request content was invalid.",
                    '401' : "Unauthorized access.",
                    '403' : "Forbidden resource can't be accessed.",
                    '500' : "Internal Server Error",
                    '503' : "Service Unavailable"
                };
                if (x.status) {
                    errorMessage = statusErrorMap[x.status];
                    if (!errorMessage) {
                        errorMessage = "Unknown Error.";
                    } else if (exception == 'parsererror') {
                        errorMessage = "Error. Parsing JSON request failed.";
                    } else if (exception == 'timeout') {
                        errorMessage = "Request timed out.";
                    } else if (exception == 'abort') {
                        errorMessage = "Request was aborted by server.";
                    } else {
                        errorMessage = "Unknown Error.";
                    }
                    $this.parent().html(errorMessage);
                    console.log("Error message is: " + errorMessage);
                } else {
                    console.log("ERROR!!");
                    console.log(e);
                }
            }
        }); // Close $.ajax
    }); // End click event
});

कार्य (फ्रंट-एंड डिस्प्ले और अजाक्स कार्रवाई)

पसंदीदा जोड़ें / निकालें लिंक को आउटपुट करने के लिए, बस इसे अपने पेज / पोस्ट पर कॉल करें:

if (function_exists('myFavoritesLink') {
    myFavoritesLink($user_ID, $post->ID);
}

फ्रंट-एंड डिस्प्ले फंक्शन:

function myFavoritesLink($user_ID, $postID)
{
    global $user_ID;
    if (is_user_logged_in()) {
        // Set initial element toggle value & link text - udpated by callback
        $myUserMeta = get_user_meta($user_ID, 'myMetadata', true);
        if (is_array($myUserMeta['metadata']) && in_array($postID, $myUserMeta['metadata'])) {
            $toggle = "y";
            $linkText = "Remove from Favorites";
        } else {
            $toggle = "n";
            $linkText = "Add to Favorites";
        }

        // Create Ajax-only nonce for initial request only
        // New nonce returned in callback
        $ajaxNonce = wp_create_nonce('myplugin_myaction_' . $postID);
        echo '<p class="faves-action"><a class="faves-link"' 
            . ' data-post-id="' . $postID 
            . '" data-user-id="' . $user_ID  
            . '" data-toggle="' . $toggle 
            . '" data-nonce="' . $ajaxNonce 
            . '" href="#">' . $linkText . '</a></p>' . "\n";

    } else {
        // User not logged in
        echo '<p>Sign in to use the Favorites feature.</p>' . "\n";
    }

}

अजाक्स कार्रवाई समारोह:

/**
* Toggle add/remove for Favorites
*/
function toggleFavorites()
{
    if (is_user_logged_in()) {
        // Verify nonce
        $ajaxNonce = 'myplugin_myaction' . $_POST['post_id'];
        if (! wp_verify_nonce($_POST['_ajax_nonce'], $ajaxNonce)) {
            exit('Sorry!');
        }
        // Process POST vars
        if (isset($_POST['post_id']) && is_numeric($_POST['post_id'])) {
            $postID = $_POST['post_id'];
        } else {
            return;
        }
        if (isset($_POST['user_id']) && is_numeric($_POST['user_id'])) {
            $userID = $_POST['user_id'];
        } else {
            return;
        }
        if (isset($_POST['the_toggle']) && ($_POST['the_toggle'] === "y" || $_POST['the_toggle'] === "n")) {
            $toggle = $_POST['the_toggle'];
        } else {
            return;
        }

        $myUserMeta = get_user_meta($userID, 'myMetadata', true);

        // Init myUserMeta array if it doesn't exist
        if ($myUserMeta['myMetadata'] === '' || ! is_array($myUserMeta['myMetadata'])) {
            $myUserMeta['myMetadata'] = array();
        }

        // Toggle the item in the Favorites list
        if ($toggle === "y" && in_array($postID, $myUserMeta['myMetadata'])) {
            // Remove item from Favorites list
            $myUserMeta['myMetadata'] = array_flip($myUserMeta['myMetadata']);
            unset($myUserMeta['myMetadata'][$postID]);
            $myUserMeta['myMetadata'] = array_flip($myUserMeta['myMetadata']);
            $myUserMeta['myMetadata'] = array_values($myUserMeta['myMetadata']);
            $newToggle = "n";
            $message = "Add to Favorites";
        } else {
            // Add item to Favorites list
            $myUserMeta['myMetadata'][] = $postID;
            $newToggle = "y";
            $message = "Remove from Favorites";
        }

        // Prep for the response
        // Nonce for next request - unique with microtime string appended
        $newNonce = wp_create_nonce('myplugin_myaction_' . $postID . '_' 
            . str_replace('.', '', gettimeofday(true)));
        $updateUserMeta = update_user_meta($userID, 'myMetadata', $myUserMeta);

        // Response to jQuery
        if($updateUserMeta === false) {
            $response['type'] = "error";
            $response['theToggle'] = $toggle;
            $response['message'] = "Your Favorites could not be updated.";
            $response['newNonce'] = $newNonce;
        } else {
            $response['type'] = "success";
            $response['theToggle'] = $newToggle;
            $response['message'] = $message;
            $response['newNonce'] = $newNonce;
        }

        // Process with Ajax, otherwise process with self
        if (! empty($_SERVER['HTTP_X_REQUESTED_WITH']) && 
            strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
                $response = json_encode($response);
                echo $response;
        } else {
            header("Location: " . $_SERVER["HTTP_REFERER"]);
        }
        exit();
    } // End is_user_logged_in()
}
add_action('wp_ajax_myFavorites', 'toggleFavorites');

3

मैं वास्तव में प्रत्येक ajax अनुरोध के लिए एक नया गैर प्राप्त करने के पीछे तर्क पर सवाल करना है। मूल nonce समाप्त हो जाएगा, लेकिन इसका उपयोग एक से अधिक बार किया जा सकता है जब तक यह नहीं करता है। जावास्क्रिप्ट के माध्यम से इसे प्राप्त करने के उद्देश्य से हार जाता है, विशेष रूप से इसे एक त्रुटि मामले पर प्रदान करना। (एक समय सीमा के भीतर उपयोगकर्ता के साथ किसी क्रिया को संबद्ध करने के लिए गैर-सुरक्षा के लिए गैर-सुरक्षा का उद्देश्य।)

मुझे अन्य उत्तरों का उल्लेख नहीं करना है, लेकिन मैं नया हूं और ऊपर टिप्पणी नहीं कर सकता, इसलिए पोस्ट किए गए "समाधान" के संबंध में, आप हर बार एक नया गैर-लाभ प्राप्त कर रहे हैं, लेकिन अनुरोध में इसका उपयोग नहीं कर रहे हैं। यह निश्चित रूप से मुश्किल होगा कि माइक्रोसेकंड्स को हर बार उसी तरह से बनाए गए प्रत्येक नए नॉन से मेल खाने के लिए उसी तरह से प्राप्त किया जाए। PHP कोड मूल nonce के खिलाफ सत्यापन कर रहा है, और जावास्क्रिप्ट मूल nonce की आपूर्ति कर रहा है ... इसलिए यह काम करता है (क्योंकि यह अभी तक समाप्त नहीं हुआ है)।


1
समस्या यह है, गैर-उपयोग समाप्त होने के बाद समाप्त हो जाती है और प्रत्येक समय के बाद अजाक्स फ़ंक्शन में -1 वापस आ जाएगी। यह समस्या है अगर आप PHP में एक फॉर्म के कुछ हिस्सों को सत्यापित कर रहे हैं और प्रिंट आउट करने के लिए त्रुटियों को वापस करते हैं। फॉर्म नॉन का उपयोग किया गया था, लेकिन त्रुटि वास्तव में खेतों के php सत्यापन में हुई थी, और जब फॉर्म फिर से जमा हो जाता है, तो इस बार सत्यापित नहीं किया जा सकता है और check_ajax_referer-1 रिटर्न करता है, जो कि हम नहीं चाहते हैं!
सोलोमन क्लॉसन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.