GET方法的REST API JWT身份验证

时间:2019-10-24 作者:Reneesh Kurian

我正在为我的Wordpress网站开发一个API,我想使用jwt令牌授权所有API请求。已安装并配置此插件“JWT Authentication for WP REST API”。但当我尝试通过get/post方法时,我的API将返回数据,而不传递jwt访问令牌,我如何防止这种情况发生?

function api_version()
{
    $api=array( "version"=> "v1",

    "time"=>date(\'Y-m-d H:i:s P\'));
    return $api;
}

add_action( \'rest_api_init\', function () {
  register_rest_route( \'v1/\', \'info\', array(
    \'methods\' => \'GET\',
    \'callback\' => \'api_version\',

  ) );
} );

2 个回复
最合适的回答,由SO网友:Jacob Peattie 整理而成

令牌只是验证来自特定用户的请求。您仍然需要使用permissions callback 检查该用户是否对您正在执行的操作具有权限。如果省略permissions_callback 参数注册路由时,则该路由是公共的。

如果只需要检查是否有用户,而不需要特定的权限,那么可以使用is_user_logged_in():

register_rest_route( \'v1/\', \'info\', array(
    \'methods\' => \'GET\',
    \'callback\' => \'api_version\',
    \'permissions_callback\' => function() {
        return is_user_logged_in();
    },
) );

SO网友:Jürgen Fink

这个问题问得好,但也不是那么容易(我花了一周时间才弄明白)。

然后我在WordPress文档中找到了两个很好的摘要:
Home / REST API Handbook / Extending the REST API / Routes and Endpoints
Home / REST API Handbook / Extending the REST API / Adding Custom Endpoints

在那里我发现了如何使用namespaces, routespermission_callback 正确地

关键部分是添加Permission Callback 进入function.php 你的主题,作为@Jacob Peattie 在他的回答中正确地提到了。

接下来,我使用if ( !isset($_COOKIE[\'wp-postpass_\'. COOKIEHASH] )) 在权限回调中(作为wp-postpass_ cookie为受密码保护的帖子保存令牌的cookie,作为is_user_logged_in() )

/**
  * This is our callback function to return (GET) our data.
  *
  * @param WP_REST_Request $request This function accepts a rest request to process data.
  */
function get_your_data($request) {
    global $wpdb;
    $yourdata = $wpdb->get_results("SELECT * FROM your_custom_table");

    return rest_ensure_response( $yourdata );
};

/**
 * This is our callback function to insert (POST) new data record.
 *
 * @param WP_REST_Request $request This function accepts a rest request to process data.
 */
function insert_your_data($request) {
    global $wpdb;
    $contentType = isset($_SERVER["CONTENT_TYPE"]) ? trim($_SERVER["CONTENT_TYPE"]) : \'\';

    if ($contentType === "application/json") {
        $content = trim(file_get_contents("php://input"));
        $decoded = json_decode($content, true);
        $newrecord = $wpdb->insert( \'your_custom_table\', array( \'column_1\' => $decoded[\'column_1\'], \'column_2\' => $decoded[\'column_2\']));
    };
    if($newrecord){
        return rest_ensure_response($newrecord);
    }else{
        //something gone wrong
        return rest_ensure_response(\'failed\');
    };

    header("Content-Type: application/json; charset=UTF-8");
};
/**
 * This is our callback function to update (PUT) a data record.
 *
 * @param WP_REST_Request $request This function accepts a rest request to process data.
 */
function update_your_data($request) {
    global $wpdb;
    $contentType = isset($_SERVER["CONTENT_TYPE"]) ? trim($_SERVER["CONTENT_TYPE"]) : \'\';

    if ($contentType === "application/json") {
        $content = trim(file_get_contents("php://input"));
        $decoded = json_decode($content, true);
        $updatedrecord = $wpdb->update( \'your_custom_table\', array( \'column_1\' => $decoded[\'column_1\'], \'column_2\' => $decoded[\'column_2\']), array(\'id\' => $decoded[\'id\']), array( \'%s\' ));
    };

    if($updatedrecord){
        return rest_ensure_response($updatedrecord);
    }else{
        //something gone wrong
        return rest_ensure_response(\'failed\');
    };

    header("Content-Type: application/json; charset=UTF-8");
};

//  Permission Callback 
// \'ypp\' is the Prefix I chose (ypp = Your Private Page)

function ypp_get_private_data_permissions_check() {
    // Restrict endpoint to browsers that have the wp-postpass_ cookie.

    if ( !isset($_COOKIE[\'wp-postpass_\'. COOKIEHASH] )) {
       return new WP_Error( \'rest_forbidden\', esc_html__( \'OMG you can not create or edit private data.\', \'my-text-domain\' ), array( \'status\' => 401 ) );
    };
    // This is a black-listing approach. You could alternatively do this via white-listing, by returning false here and changing the permissions check.
    return true;
};

// And then add the permission_callback to your POST and PUT routes:

add_action(\'rest_api_init\', function() {
    /**
    * Register here your custom routes for your CRUD functions
    */
    register_rest_route( \'your_private_page/v1\', \'/data\', array(
       array(
          \'methods\'  => WP_REST_Server::READABLE,
          \'callback\' => \'get_your_data\',
          // Always allow.
          \'permission_callback\' => \'__return_true\' // <-- you can protect GET as well if your like
       ),
       array(
          \'methods\'  => WP_REST_Server::CREATABLE,
          \'callback\' => \'insert_your_data\',
          // Here we register our permissions callback. The callback is fired before the main callback to check if the current user can access the endpoint.
          \'permission_callback\' => \'ypp_get_private_data_permissions_check\', // <-- that was the missing part
       ),
       array(
          \'methods\'  => WP_REST_Server::EDITABLE,
          \'callback\' => \'update_your_data\',
          // Here we register our permissions callback. The callback is fired before the main callback to check if the current user can access the endpoint.
          \'permission_callback\' => \'ypp_get_private_data_permissions_check\', // <-- that was the missing part
       ),
    ));
});
如果您愿意,我发布了一个问题(与您关于JWT认证的问题类似),然后在答案中给出了我的发现,因为它最终起到了作用。

Full story 完整代码位于:
How to force Authentication on REST API for Password protected page using custom table and fetch() without Plugin

希望这有点帮助。