WordPress REST API v2 uç noktalarını genel görünümden gizleme


15

Sitemden bilgi sorgulamak için WordPress REST API v2 kullanmaya başlamak istiyorum. Doğrudan bir uç nokta URL'sini ziyaret ettiğimde, tüm verileri herkese açık olarak görebildiğimi fark ettim. Ayrıca birçok öğreticinin canlı siteler yerine test veya yerel sunucuların kullanımından bahsettiğini gördüm.

Sorularım:

  • Bu, üretim yerlerinde kullanılması mı amaçlanıyor?
  • /wp-json/wp/v2/users/Siteye kayıtlı tüm kullanıcıları gösteren gibi, uç noktaların herkes tarafından görüntülenmesine izin vermek için bir güvenlik riski var mı ?
  • Yalnızca yetkili kullanıcıların bir uç noktaya erişmesine izin vermek mümkün müdür?

Güvenlikle ilgili en iyi uygulamaları izlediğimden emin olmak istiyorum, bu nedenle ipuçları yararlı olacaktır. API docs kimlik söz ama doğrudan erişilen URL'yi nasıl önleneceği emin değilim. Diğerleri genellikle bu verilere, çok fazla bilgi göstermeden harici uygulamalar tarafından erişilecek şekilde nasıl ayarlar?


1
Asıl soru, uç nokta istemci tarafını (yani AJAX çağrılarında) veya sunucu tarafını (belki de başka bir uygulamadan) mı kullanıyorsunuz?
TheDeadMedic

1
Not: WordFence eklentisinin en son sürümü, "/? Author = N 'taramaları, oEmbed API'si ve WordPress REST API'si aracılığıyla kullanıcı adlarının bulunmasını engelleme" seçeneğine sahiptir
squarecandy

Yanıtlar:


18

Bu, üretim yerlerinde kullanılması mı amaçlanıyor?

Evet. Birçok site zaten kullanıyor .

Siteye kayıtlı tüm kullanıcıları gösteren / wp-json / wp / v2 / users / gibi uç noktaların herkes tarafından görüntülenmesine izin vermek için bir güvenlik riski var mı?

Hayır. Sunucunun yanıtlarının güvenlikle ilgisi yoktur, boş bir ekran / salt okunur erişim ile neler yapabilirsiniz? Hiçbir şey değil!

Ancak, siteleriniz zayıf parolalara izin veriyorsa, bazı sorunlar vardır . Ancak sitelerinizin politikası, REST API bu konuda hiçbir şey bilmiyor.

Yalnızca yetkili kullanıcıların bir uç noktaya erişmesine izin vermek mümkün müdür?

Evet. İzin geri aramasını kullanarak bunu yapabilirsiniz .

Örneğin:

if ( 'edit' === $request['context'] && ! current_user_can( 'list_users' ) ) {
    return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you cannot view this resource with edit context.' ), array( 'status' => rest_authorization_required_code() ) );
}

Diğerleri genellikle bu verilere, çok fazla bilgi göstermeden harici uygulamalar tarafından erişilecek şekilde nasıl ayarlar?

Bu soruya cevap vermek zordur çünkü ne / ne zaman çok fazla bilgi olduğunu bilmiyoruz . Ama hepimiz referanslar ve hile sayfaları kullanıyoruz .


1
Dikkat edilmesi gereken nokta: "Pozlama, REST API'si aracılığıyla açıklanacak şekilde ayarlanmış yayın türleri kullanan kullanıcılarla sınırlıdır." - yani, her müşterinin bir kullanıcısı olan bir çevrimiçi mağaza dediyseniz, bu kullanıcılar açıkta kalmaz /wp-json/wp/v2/users/. (Referans wordpress.stackexchange.com/q/252328/41488 @JHoffmann yorum)
squarecandy

'X-WP-Nonce' başlığında REST tabanlı bir nonce wp_create_nonce ('wp_rest') olması gerektiğine dikkat edilmelidir, aksi takdirde bunların hiçbiri işe yaramaz ve her zaman 403 döndürür.
Andrew Killen

5

Yalnızca yetkili kullanıcıların bir uç noktaya erişmesine izin vermek mümkün müdür?

API uç noktanıza içeriği görüntülemek için kimlik doğrulaması gerektiren özel bir izin geri araması eklemek mümkündür. Yetkisiz kullanıcılar bir hata yanıtı alır"code": "rest_forbidden"

Bunu yapmanın en basit yolu WP_REST_Posts_Controller'ı genişletmektir. İşte bunun çok basit bir örneği:

class My_Private_Posts_Controller extends WP_REST_Posts_Controller {

   /**
   * The namespace.
   *
   * @var string
   */
   protected $namespace;

   /**
   * The post type for the current object.
   *
   * @var string
   */
   protected $post_type;

   /**
   * Rest base for the current object.
   *
   * @var string
   */
   protected $rest_base;

  /**
   * Register the routes for the objects of the controller.
   * Nearly the same as WP_REST_Posts_Controller::register_routes(), but with a 
   * custom permission callback.
   */
  public function register_routes() {
    register_rest_route( $this->namespace, '/' . $this->rest_base, array(
        array(
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => array( $this, 'get_items' ),
            'permission_callback' => array( $this, 'get_items_permissions_check' ),
            'args'                => $this->get_collection_params(),
            'show_in_index'       => true,
        ),
        array(
            'methods'             => WP_REST_Server::CREATABLE,
            'callback'            => array( $this, 'create_item' ),
            'permission_callback' => array( $this, 'create_item_permissions_check' ),
            'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ),
            'show_in_index'       => true,
        ),
        'schema' => array( $this, 'get_public_item_schema' ),
    ) );

    register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array(
        array(
            'methods'             => WP_REST_Server::READABLE,
            'callback'            => array( $this, 'get_item' ),
            'permission_callback' => array( $this, 'get_item_permissions_check' ),
            'args'                => array(
                'context' => $this->get_context_param( array( 'default' => 'view' ) ),
            ),
            'show_in_index'       => true,
        ),
        array(
            'methods'             => WP_REST_Server::EDITABLE,
            'callback'            => array( $this, 'update_item' ),
            'permission_callback' => array( $this, 'update_item_permissions_check' ),
            'args'                => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
            'show_in_index'       => true,
        ),
        array(
            'methods'             => WP_REST_Server::DELETABLE,
            'callback'            => array( $this, 'delete_item' ),
            'permission_callback' => array( $this, 'delete_item_permissions_check' ),
            'args'                => array(
                'force' => array(
                    'default'     => true,
                    'description' => __( 'Whether to bypass trash and force deletion.' ),
                ),
            ),
            'show_in_index'       => false,
        ),
        'schema' => array( $this, 'get_public_item_schema' ),
    ) );     
  }

  /**
   * Check if a given request has access to get items
   *
   * @param WP_REST_Request $request Full data about the request.
   * @return WP_Error|bool
   */
  public function get_items_permissions_check( $request ) {
    return current_user_can( 'edit_posts' );
  }

}

Erişime izin verilip verilmeyeceğini belirlemek için izin geri aramasının function get_items_permissions_checkkullandığı fark edilir current_user_can. API'yı nasıl kullandığınıza bağlı olarak, istemci kimlik doğrulaması hakkında daha fazla bilgi edinmeniz gerekebilir.

Ardından, aşağıdaki değişkenleri ekleyerek özel yayın türünüzü REST API desteği ile kaydedebilirsiniz. register_post_type

  /**
   * Register a book post type, with REST API support
   *
   * Based on example at: http://codex.wordpress.org/Function_Reference/register_post_type
   */
  add_action( 'init', 'my_book_cpt' );
  function my_book_cpt() {
    $labels = array(
        'name'               => _x( 'Books', 'post type general name', 'your-plugin-textdomain' ),
        'singular_name'      => _x( 'Book', 'post type singular name', 'your-plugin-textdomain' ),
        'menu_name'          => _x( 'Books', 'admin menu', 'your-plugin-textdomain' ),
        'name_admin_bar'     => _x( 'Book', 'add new on admin bar', 'your-plugin-textdomain' ),
        'add_new'            => _x( 'Add New', 'book', 'your-plugin-textdomain' ),
        'add_new_item'       => __( 'Add New Book', 'your-plugin-textdomain' ),
        'new_item'           => __( 'New Book', 'your-plugin-textdomain' ),
        'edit_item'          => __( 'Edit Book', 'your-plugin-textdomain' ),
        'view_item'          => __( 'View Book', 'your-plugin-textdomain' ),
        'all_items'          => __( 'All Books', 'your-plugin-textdomain' ),
        'search_items'       => __( 'Search Books', 'your-plugin-textdomain' ),
        'parent_item_colon'  => __( 'Parent Books:', 'your-plugin-textdomain' ),
        'not_found'          => __( 'No books found.', 'your-plugin-textdomain' ),
        'not_found_in_trash' => __( 'No books found in Trash.', 'your-plugin-textdomain' )
    );

    $args = array(
        'labels'             => $labels,
        'description'        => __( 'Description.', 'your-plugin-textdomain' ),
        'public'             => true,
        'publicly_queryable' => true,
        'show_ui'            => true,
        'show_in_menu'       => true,
        'query_var'          => true,
        'rewrite'            => array( 'slug' => 'book' ),
        'capability_type'    => 'post',
        'has_archive'        => true,
        'hierarchical'       => false,
        'menu_position'      => null,
        'show_in_rest'       => true,
        'rest_base'          => 'books-api',
        'rest_controller_class' => 'My_Private_Posts_Controller',
        'supports'           => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' )
    );

    register_post_type( 'book', $args );
}

Varsayılan denetleyici yerine rest_controller_classkullanımları göreceksiniz My_Private_Posts_Controller.

Belgelerin dışında REST API'sini kullanmak için iyi örnekler ve açıklamalar bulmakta zorlanıyorum . Varsayılan denetleyiciyi genişletmenin bu harika açıklamasını buldum ve işte uç noktaları eklemek için çok kapsamlı bir kılavuz .


2

İşte oturum açmamış tüm kullanıcıların REST API'sini kullanmasını engellemek için kullandığım şey:

add_filter( 'rest_api_init', 'rest_only_for_authorized_users', 99 );
function rest_only_for_authorized_users($wp_rest_server){
    if ( !is_user_logged_in() ) {
        wp_die('sorry you are not allowed to access this data','cheatin eh?',403);
    }
}

Geri kalan bitiş noktasının kullanımı genişleyeceğinden, bu tür bir strateji sorunlu hale gelecektir. Sonunda wp-json bitiş noktası admin-ajax'ın yerini alacak, yani her türlü meşru ön uç isteği de olacak. Her neyse, 403 ile ölmek içerik olarak yorumlanabilecek bir şeyden daha iyidir.
Mark Kaplun

@MarkKaplun - evet, bu konuda haklısın. Bu, aslında hiç genel veri sunan bir site bağlamında kullanıyorum ve kullanıcılar, kullanıcı meta, özel posta türü verileri, vb. . Belirli verilerin gizli olduğundan emin olmak için klasik WP şablon yapısı içinde bir sürü iş yaptığınızda ve birdenbire REST API aracılığıyla herkesin erişebildiğini fark ettiğinizde berbat. Neyse, bir 403 hizmet hakkında iyi bir nokta ...
squarecandy

0
add_filter( 'rest_api_init', 'rest_only_for_authorized_users', 99 );
function rest_only_for_authorized_users($wp_rest_server)
{
if( !is_user_logged_in() ) 

    wp_die('sorry you are not allowed to access this data','Require Authentication',403);
} } 
function json_authenticate_handler( $user ) {

global $wp_json_basic_auth_error;

$wp_json_basic_auth_error = null;

// Don't authenticate twice
if ( ! empty( $user ) ) {
    return $user;
}

if ( !isset( $_SERVER['PHP_AUTH_USER'] ) ) {
    return $user;
}

$username = $_SERVER['PHP_AUTH_USER'];
$password = $_SERVER['PHP_AUTH_PW'];


remove_filter( 'determine_current_user', 'json_authenticate_handler', 20 );

$user = wp_authenticate( $username, $password );

add_filter( 'determine_current_user', 'json_authenticate_handler', 20 );

if ( is_wp_error( $user ) ) {
    $wp_json_basic_auth_error = $user;
    return null;
}

$wp_json_basic_auth_error = true;

return $user->ID;}add_filter( 'determine_current_user', 'json_authenticate_handler', 20 );

1
OP'nin sorularına neden ve nasıl cevap verdiğini metinde ayrıntılı olarak açıklayabilir misiniz?
kero

Bu op'un cevabı değil ve pratikte nasıl çalışılacağını göstermek için sadece kod verdim ve programlı olarak kolayca anlaşılmaya çalıştım Eğer anladıysanız
dipel patel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.