REST API से पुनर्प्राप्त गैरकानूनी अमान्य है और wp_localize_script में उत्पन्न नॉन से अलग है


10

उन लोगों के लिए जो Google से आते हैं: आपको शायद REST API से नॉनवेज नहीं मिलना चाहिए , जब तक कि आप वास्तव में नहीं जानते कि आप क्या कर रहे हैं। REST API साथ कुकी-आधारित प्रमाणीकरण केवल है मतलब प्लगइन्स और विषयों के लिए। एक पृष्ठ के आवेदन के लिए, आपको शायद OAuth का उपयोग करना चाहिए ।

यह प्रश्न इसलिए मौजूद है क्योंकि दस्तावेज़ीकरण इस बात पर स्पष्ट नहीं है कि आपको वास्तव में कैसे प्रमाणित करना चाहिए जब एकल पृष्ठ ऐप्स का निर्माण किया जाता है, JWTs वास्तव में वेब ऐप्स के लिए फिट नहीं होते हैं, और OAuth कुकी आधारित नीति की तुलना में लागू करना कठिन है।


हैंडबुक में एक उदाहरण है कि बैकबोन जावास्क्रिप्ट क्लाइंट नॉनस को कैसे संभालता है, और यदि मैं उदाहरण का पालन करता हूं, तो मुझे एक ऐसा नॉन्स मिलता है जो बिल्ट इन एंडपॉइंट्स जैसे / wp / v2 / पोस्ट स्वीकार करता है।

\wp_localize_script("client-js", "theme", [
  'nonce' => wp_create_nonce('wp_rest'),
  'user' => get_current_user_id(),

]);

हालांकि, बैकबोन का उपयोग करना सवाल से बाहर है, और इसलिए थीम हैं, इसलिए मैंने निम्नलिखित प्लगइन लिखा है:

<?php
/*
Plugin Name: Nonce Endpoint
*/

add_action('rest_api_init', function () {
  $user = get_current_user_id();
  register_rest_route('nonce/v1', 'get', [
    'methods' => 'GET',
    'callback' => function () use ($user) {
      return [
        'nonce' => wp_create_nonce('wp_rest'),
        'user' => $user,
      ];
    },
  ]);

  register_rest_route('nonce/v1', 'verify', [
    'methods' => 'GET',
    'callback' => function () use ($user) {
      $nonce = !empty($_GET['nonce']) ? $_GET['nonce'] : false;
      return [
        'valid' => (bool) wp_verify_nonce($nonce, 'wp_rest'),
        'user' => $user,
      ];
    },
  ]);
});

मैंने जावास्क्रिप्ट में थोड़ा सा कंसोल किया, और निम्नलिखित लिखा:

var main = async () => { // var because it can be redefined
  const nonceReq = await fetch('/wp-json/nonce/v1/get', { credentials: 'include' })
  const nonceResp = await nonceReq.json()
  const nonceValidReq = await fetch(`/wp-json/nonce/v1/verify?nonce=${nonceResp.nonce}`, { credentials: 'include' })
  const nonceValidResp = await nonceValidReq.json()
  const addPost = (nonce) => fetch('/wp-json/wp/v2/posts', {
    method: 'POST',
    credentials: 'include',
    body: JSON.stringify({
      title: `Test ${Date.now()}`,
      content: 'Test',
    }),
    headers: {
      'X-WP-Nonce': nonce,
      'content-type': 'application/json'
    },
  }).then(r => r.json()).then(console.log)

  console.log(nonceResp.nonce, nonceResp.user, nonceValidResp)
  console.log(theme.nonce, theme.user)
  addPost(nonceResp.nonce)
  addPost(theme.nonce)
}

main()

अपेक्षित परिणाम दो नए पोस्ट हैं, लेकिन मैं Cookie nonce is invalidपहले एक से प्राप्त करता हूं , और दूसरा एक पोस्ट को सफलतापूर्वक बनाता है। ऐसा शायद इसलिए है क्योंकि गैर अलग हैं, लेकिन क्यों? मैं दोनों अनुरोधों में एक ही उपयोगकर्ता के रूप में लॉग इन हूं।

यहाँ छवि विवरण दर्ज करें

यदि मेरा दृष्टिकोण गलत है, तो मुझे गैर कैसे प्राप्त करना चाहिए?

संपादित करें :

मैंने बहुत किस्मत के बिना ग्लोबल्स के साथ खिलवाड़ करने की कोशिश की । Wp_loaded कार्रवाई का उपयोग करके थोड़ा भाग्यशाली मिला:

<?php
/*
Plugin Name: Nonce Endpoint
*/

$nonce = 'invalid';
add_action('wp_loaded', function () {
  global $nonce;
  $nonce = wp_create_nonce('wp_rest');
});

add_action('rest_api_init', function () {
  $user = get_current_user_id();
  register_rest_route('nonce/v1', 'get', [
    'methods' => 'GET',
    'callback' => function () use ($user) {
      return [
        'nonce' => $GLOBALS['nonce'],
        'user' => $user,
      ];
    },
  ]);

  register_rest_route('nonce/v1', 'verify', [
    'methods' => 'GET',
    'callback' => function () use ($user) {
      $nonce = !empty($_GET['nonce']) ? $_GET['nonce'] : false;
      error_log("verify $nonce $user");
      return [
        'valid' => (bool) wp_verify_nonce($nonce, 'wp_rest'),
        'user' => $user,
      ];
    },
  ]);
});

अब जब मैं ऊपर दिए गए जावास्क्रिप्ट को चलाता हूं, तो दो पोस्ट बन जाते हैं, लेकिन सत्यापित समापन बिंदु विफल हो जाता है!

यहाँ छवि विवरण दर्ज करें

मैं wp_verify_nonce डिबग करने गया:

function wp_verify_nonce( $nonce, $action = -1 ) {
  $nonce = (string) $nonce;
  $user = wp_get_current_user();
  $uid = (int) $user->ID; // This is 0, even though the verify endpoint says I'm logged in as user 2!

मैंने कुछ लॉगिंग जोड़ी

// Nonce generated 0-12 hours ago
$expected = substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce'), -12, 10 );
error_log("expected 1 $expected received $nonce uid $uid action $action");
if ( hash_equals( $expected, $nonce ) ) {
  return 1;
}

// Nonce generated 12-24 hours ago
$expected = substr( wp_hash( ( $i - 1 ) . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
error_log("expected 2 $expected received $nonce uid $uid action $action");
if ( hash_equals( $expected, $nonce ) ) {
  return 2;
}

और जावास्क्रिप्ट कोड अब निम्नलिखित प्रविष्टियों में परिणाम है। जैसा कि आप देख सकते हैं, जब सत्यापित समापन बिंदु कहा जाता है, तो uid 0 है।

[01-Mar-2018 11:41:57 UTC] verify 716087f772 2
[01-Mar-2018 11:41:57 UTC] expected 1 b35fa18521 received 716087f772 uid 0 action wp_rest
[01-Mar-2018 11:41:57 UTC] expected 2 dd35d95cbd received 716087f772 uid 0 action wp_rest
[01-Mar-2018 11:41:58 UTC] expected 1 716087f772 received 716087f772 uid 2 action wp_rest
[01-Mar-2018 11:41:58 UTC] expected 1 716087f772 received 716087f772 uid 2 action wp_rest

जवाबों:


3

पर एक करीब से देखो function rest_cookie_check_errors()

जब आप के माध्यम से गैर प्राप्त करते हैं /wp-json/nonce/v1/get, तो आप पहली बार में एक गैर भेज नहीं रहे हैं। तो यह फ़ंक्शन इस कोड के साथ, आपके प्रमाणीकरण को शून्य कर देता है:

if ( null === $nonce ) {
    // No nonce at all, so act as if it's an unauthenticated request.
    wp_set_current_user( 0 );
    return true;
}

यही कारण है कि आप अपने REST कॉल बनाम थीम से इसे प्राप्त करने के लिए एक अलग नॉनस कर रहे हैं। REST कॉल जानबूझकर आपके लॉगिन क्रेडेंशियल (इस मामले में कुकी ऑर्ट के माध्यम से) को पहचान नहीं रही है क्योंकि आपने अनुरोध में एक वैध नॉनस नहीं भेजा था।

अब, आपके wp_loaded कोड के काम करने का कारण यह था कि आपको नॉन मिला और इस वैश्विक कोड को सहेजने से पहले इस बाकी कोड ने आपके लॉगिन को शून्य कर दिया। सत्यापन विफल हो जाता है क्योंकि सत्यापित होने से पहले बाकी कोड आपके लॉगिन को बंद कर देता है।


मैंने उस फ़ंक्शन को देखा भी नहीं है, लेकिन यह शायद समझ में आता है। बात यह है कि, मुझे GET अनुरोध के लिए एक वैध गैर क्यों शामिल करना चाहिए? (मैं इसे अभी प्राप्त करता हूं, लेकिन यह स्पष्ट से बहुत दूर है) / सत्यापित समापन बिंदु की पूरी बात यह है कि मैं जांच सकता हूं कि क्या नॉन अभी भी वैध है, और अगर यह बासी हो रहा है या मान्य नहीं है, तो एक नया नॉनस प्राप्त करें।
क्रिश्चियन

Rest_cookie_check_errors के स्रोत के आधार पर, मुझे अपना समापन बिंदु बदलना चाहिए ताकि यह जांच न करे $_GET['nonce'], लेकिन नॉन हेडर या $_GET['_wpnonce']पैरामीटर। सही बात?
क्रिश्चियन

1

जबकि यह समाधान काम करता है, यह अनुशंसित नहीं है । OAuth पसंदीदा विकल्प है।


मैने सोचा कि मैंने पा लिया।

मुझे लगता है कि wp_verify_nonce टूट गया है, क्योंकि wp_get_current_user उचित उपयोगकर्ता ऑब्जेक्ट प्राप्त करने में विफल रहता है।

ऐसा नहीं है, जैसा कि ओटो द्वारा सचित्र है।

सौभाग्य से इसमें एक फ़िल्टर है: $uid = apply_filters( 'nonce_user_logged_out', $uid, $action );

इस फ़िल्टर का उपयोग करके मैं निम्नलिखित लिखने में सक्षम था, और जावास्क्रिप्ट कोड को इस तरह निष्पादित करना चाहिए:

यहाँ छवि विवरण दर्ज करें

<?php
/*
Plugin Name: Nonce Endpoint
*/

$nonce = 'invalid';
add_action('wp_loaded', function () {
  global $nonce;
  $nonce = wp_create_nonce('wp_rest');
});

add_action('rest_api_init', function () {
  $user = get_current_user_id();
  register_rest_route('nonce/v1', 'get', [
    'methods' => 'GET',
    'callback' => function () use ($user) {
      return [
        'nonce' => $GLOBALS['nonce'],
        'user' => $user,
      ];
    },
  ]);

  register_rest_route('nonce/v1', 'verify', [
    'methods' => 'GET',
    'callback' => function () use ($user) {
      $nonce = !empty($_GET['nonce']) ? $_GET['nonce'] : false;
      add_filter("nonce_user_logged_out", function ($uid, $action) use ($user) {
        if ($uid === 0 && $action === 'wp_rest') {
          return $user;
        }

        return $uid;
      }, 10, 2);

      return [
        'status' => wp_verify_nonce($nonce, 'wp_rest'),
        'user' => $user,
      ];
    },
  ]);
});

यदि आप एक सुरक्षा समस्या को ठीक करते हैं, तो कृपया मुझे एक चिल्लाओ, अभी मैं इसके साथ कुछ भी गलत नहीं देख सकता, ग्लोबल्स के अलावा।


0

इस सभी कोड को देखकर ऐसा लगता है जैसे आपकी समस्या क्लोजर का उपयोग है। पर initमंच आप केवल हुक स्थापित करना चाहिए और सभी कोर के नहीं के रूप में डेटा का मूल्यांकन नहीं कर समाप्त लोड हो रहा है था और प्रारंभ किया जा रहा।

में

add_action('rest_api_init', function () {
  $user = get_current_user_id();
  register_rest_route('nonce/v1', 'get', [
    'methods' => 'GET',
    'callback' => function () use ($user) {
      return [
        'nonce' => $GLOBALS['nonce'],
        'user' => $user,
      ];
    },
  ]);

$userजल्दी ही है बंद में इस्तेमाल किया जाएगा, लेकिन आप के लिए कोई भी वादे कुकी पहले से ही नियंत्रित किया गया था कि और एक उपयोगकर्ता उन पर आधारित प्रमाणीकृत किया गया। एक बेहतर कोड होगा

add_action('rest_api_init', function () {
  register_rest_route('nonce/v1', 'get', [
    'methods' => 'GET',
    'callback' => function () {
    $user = get_current_user_id();
      return [
        'nonce' => $GLOBALS['nonce'],
        'user' => $user,
      ];
    },
  ]);

जैसा कि हमेशा वर्डप्रेस में कुछ भी हुक के साथ होता है, नवीनतम हुक का उपयोग संभव है और कभी भी आपके पास कुछ भी नहीं होने का पूर्वाभास करने का प्रयास करें।


मैंने कौन से रन और किस क्रम में स्थापित करने के लिए क्वेरी मॉनिटर और एक्शन सेक्शन का इस्तेमाल किया, किस क्रम में, सेट करें_ऑर्ट और after_setup_theme से पहले चलाता है, वहाँ $ उपयोगकर्ता के बाहर और इससे पहले परिभाषित होने के साथ कोई समस्या नहीं होनी चाहिए।
क्रिश्चियन

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