Ocultando os endpoints do WordPress REST API v2 da visualização pública

8

Gostaria de começar a usar a API REST do WordPress v2 para consultar informações do meu site. Percebi que, quando visito diretamente um URL do ponto de extremidade, posso ver todos os dados publicamente. Eu também vi que muitos tutoriais mencionam o uso de servidores de teste ou locais em vez de sites ao vivo.

Minhas perguntas são:

  • Isso deve ser usado em sites em produção?
  • Existe uma segurança risco de permitir que os endpoints sejam vistos por qualquer pessoa, como /wp-json/wp/v2/users/ que mostra todos os usuários registrados no site?
  • É possível permitir que apenas usuários autorizados acessem um endpoint?

Eu quero ter certeza de que estou seguindo as práticas recomendadas relacionadas à segurança, por isso, algumas dicas podem ser úteis. Os api docs mencionam autenticação, mas não sei como evitar que o URL seja acessado diretamente. Como os outros geralmente configuram esses dados para serem acessados por aplicativos externos sem expor muita informação?

    
por Morgan 02.06.2016 / 17:39

4 respostas

12
  

Isto é para ser usado em sites em produção?

Sim! Muitos sites já o estão usando .

  

Existe um risco de segurança ao permitir que os endpoints sejam vistos por qualquer pessoa, como / wp-json / wp / v2 / users / que mostra todos os usuários registrados no site?

Não! As respostas do servidor não têm nada a ver com segurança, o que você pode fazer com um acesso de tela em branco / somente leitura? Nada!

No entanto, se seus sites permitirem senhas fracas, haverá alguns problemas . Mas é a política de seus sites, a API REST não sabe nada sobre isso.

  

É possível permitir que apenas usuários autorizados acessem um endpoint?

Sim! Você pode fazer isso usando retorno de chamada de permissão .

Exemplo de usuários 'permissão verificar retorno de chamada :

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() ) );
}
  

Como os outros geralmente configuram esses dados para serem acessados por aplicativos externos sem expor muita informação?

Essa pergunta é difícil de responder porque não sabemos o que / quando é muita informação . Mas todos nós estamos usando referências e cheatsheets .

    
por MinhTri 03.06.2016 / 07:08
5
  

É possível permitir que apenas usuários autorizados acessem um endpoint?

É possível adicionar um retorno de chamada de permissão personalizado ao ponto de extremidade da API, que requer autenticação para exibir o conteúdo. Usuários não autorizados receberão uma resposta de erro "code": "rest_forbidden"

A maneira mais simples de fazer isso é estender o WP_REST_Posts_Controller. Aqui está um exemplo muito simples disso:

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

}

Você notará que o retorno de chamada de permissões function get_items_permissions_check usa current_user_can para determinar se deve permitir o acesso. Dependendo de como você está usando a API, talvez seja necessário aprender mais sobre autenticação de clientes.

Em seguida, você pode registrar seu tipo de postagem personalizado com o suporte da API REST, adicionando os seguintes argumentos em 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 );
}

Você verá rest_controller_class usa My_Private_Posts_Controller em vez do controlador padrão.

Eu achei difícil encontrar bons exemplos e explicações para usar a API REST fora da documentação . Eu encontrei esta grande explicação de como estender o controlador padrão , e aqui está uma guia completo para adicionar endpoints .

    
por Dalton 19.07.2016 / 19:49
1

Aqui está o que eu usei para impedir que todos os usuários não logados usem a API REST:

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);
    }
}
    
por squarecandy 01.12.2017 / 03:48
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 );
    
por dipen patel 08.01.2018 / 12:56