0

我正在使用 PHP(Codeigniter)开发 REST API,并尝试为 API 访问实现 oauth 2-legged 身份验证。将使用开发人员在将我们的 API 与网站或移动应用程序集成时在编码中使用的一对凭据访问 API(因此没有最终用户授权网站或移动应用程序)。

到目前为止,我实施的看起来像是 0-legged。我只是使用消费者秘密和空访问令牌对请求进行 oauth 签名(HMAC_SHA1)。但是根据我在其他地方读到的一些答案,签署请求并验证签名是 oauth 2-leg 实施所需要做的一切(参见https://www.quora.com/What-are-the-specific -两腿和三腿OAuth提供者实现之间的差异

这是我目前拥有的 PHP 实现的客户端;

    <?php
// Just a demo for the client side implementation of oauth signed requests.

require_once ("oauth/oauth.php"); // Google oauth library 

function send_request($method = '', $api_endpoint = '',$request_params = array()){
    $consumer = new OAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
    $sig_method = new OAuthSignatureMethod_HMAC_SHA1;

    //use oauth lib to sign request
    $req = OAuthRequest::from_consumer_and_token($consumer, null, $method, $api_endpoint, $request_params);
    $sig_method = new OAuthSignatureMethod_HMAC_SHA1();
    $req->sign_request($sig_method, $consumer, null);//note: double entry of token

    if($method == 'GET'){
        echo "<br />".$req->to_url();
        $ch = curl_init($req->to_url());
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);

        $result = curl_exec($ch);
        $curl_info = curl_getinfo($ch);
        //print_r($curl_info);
        $error = curl_error($ch);
        //print_r($error);
        curl_close($ch);

        return $result;

    }elseif($method == 'POST'){

        $ch = curl_init(); 
        curl_setopt($ch,CURLOPT_URL,$api_endpoint);                   
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);        
        curl_setopt($ch, CURLOPT_HEADER,'Content-Type: application/x-www-form-urlencoded');
        //echo "<br />".$req->to_url();
        //echo "<br />Post data: ".$req->to_postdata();
        //curl_setopt($ch, CURLOPT_POSTFIELDS, $req->to_postdata());
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($request_params));

        $result = curl_exec($ch);
        $curl_info = curl_getinfo($ch);        
        print_r($curl_info);
        $error = curl_error($ch);
        //print_r($error);
        curl_close($ch);            

        return $result;
    }
}

// API consumer key and secret
define('CONSUMER_KEY', 'd4hkilp1z0pqj7158y0j');
define('CONSUMER_SECRET', 'rqhzan3mdx7wov3gvh4u');

// Authorize 
// Get products from odw api
$api_endpoint = 'http://testgapi.local/api/product/search'; // search/format/json , search/format/xml
$request_params = array();
$request_params['category_type'] = 'Tour';
$request_params['location'] = 'Las Vegas';
$request_params['start_date'] = '09/22/2015';
$request_params['end_date'] = '12/31/2015';

$result = send_request('GET', $api_endpoint, $request_params); // Call REST service with GET method
//$result = send_request('POST', $api_endpoint, $request_params);

print_r($result);
//echo $result;
?>

请求的服务器端验证(在 Codeigniter 中).. controllers/api/Product.php;

<?php
defined('BASEPATH') or exit('No direct script access allowed');

require APPPATH . '/libraries/REST_Controller.php';

class Product extends REST_Controller
{

    var $valid_request;

    function __construct()
    {
        // Construct the parent class
        parent::__construct();

        $this->load->library('Oauth_server');
    }

    public function search_get()
    {
        $this->valid_request = $this->oauth_server->validate_request();

        if (!$this->valid_request)
        {
            $response = array(
                'status' => "Failed",
                'error_message' => "Access Denied.",
                );
            return $this->response($response, 201); // NO_CONTENT (204) being the HTTP response code
        } else
        {
            // Do something
        }
    }
} // End of class
?>

库/Oauth_server.php;

<?php
require_once (APPPATH . "libraries/oauth/oauth.php"); // Google oauth library

class Oauth_server {

    var $CI;
    function __construct(){
        // Nothing to do yet.
        $this->CI = &get_instance();
    }

    function validate_request(){
        //echo "<br />".
        $consumer_key = !empty($_REQUEST['oauth_consumer_key'])? $_REQUEST['oauth_consumer_key'] : ""; 
        // Use the oauth_consumer_key in the client request to find the secret in our system. 
        $secret = $this->get_consumer_secret($consumer_key);

        $consumer = new OAuthConsumer($consumer_key, $secret);
        $sig_method = new OAuthSignatureMethod_HMAC_SHA1;

        //echo "<br />Method: ".
        $method = $_SERVER['REQUEST_METHOD'];
        //echo "<br />URI: ".
        $uri = 'http://'.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
        $sig = $_REQUEST['oauth_signature'];    
        $req = new OAuthRequest($method, $uri);

        //token is null because we're doing 2-leg
        return $sig_method->check_signature( $req, $consumer, null, $sig );
    }

    function get_consumer_secret($consumer_key){
        // Fetch the associated consumer secret from the db using the consumer key.
        $query = $this->CI->db->query("SELECT consumer_secret FROM gapi_users WHERE consumer_key = ?", array($consumer_key));
        $result = $query->row_array();

        if(!empty($result)){
            return $result['consumer_secret'];
        }
        else{
            return false;
        }
    }    
}
?>

我猜我们还可以强制通过 https 完成请求以增加安全性。

假设我要坚持使用 oauth,我想知道,如果我当前的实现是 2-legged 吗?如果不是,对于我的场景来说,两条腿肯定是一种更安全的方式吗?

非常感谢任何帮助。

4

0 回答 0