如何通过CURL命令在REST API中使用OAuth身份验证?


18

我正在尝试将WordPress Rest Api与身份验证结合使用,以从API获取更多数据。我已经安装了Oauth插件,rest-api插件,并从WP-CLI获得了API凭据。

我已经弄清楚了如何在未经授权的情况下访问数据。这有效:

// set our end point
$domain = "http://localhost/wp-api";
$endpoint = $domain."/wp-json/wp/v2/posts/";


$curl = curl_init($endpoint);

curl_setopt_array($curl, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_URL            => $endpoint,
]);
$response = curl_exec($curl);
$decoderesponse = json_decode($response, true);

?>

<pre>
  <?php print_r($decoderesponse); ?>
</pre>

但是我不知道如何使用凭据进行身份验证。这是我的尝试。我不确定“密钥”和“秘密”是否正确。

// Oauth credentials from wp-cli
$ID = "4";
$Key = "l8XZD9lX89kb";
$Secret = "UUbcc8vjUkGjuDyvK1gRTts9sZp2N8k9tbIQaGjZ6SNOyR4d";

// set our end point
$domain = "http://localhost/wp-api";
$endpoint = $domain."/wp-json/wp/v2/posts/1/revisions";

$headers[] = "key=$Key";
$headers[] = "secret=$Secret";

$curl = curl_init($endpoint);

curl_setopt_array($curl, [
  CURLOPT_HTTPHEADER     => $headers,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_URL            => $endpoint,
]);
$response = curl_exec($curl);
$decoderesponse = json_decode($response, true);

?>

<pre>
  <?php print_r($decoderesponse); ?>
</pre>

输出是

Array
(
    [code] => rest_cannot_read
    [message] => Sorry, you cannot view revisions of this post.
    [data] => Array
        (
            [status] => 401
        )
)

我该如何工作?谢谢。


2
事情并不是那么容易。我一直在尝试写一个答案,但时间很长。您可以先阅读文档,特别是The Authorization Flow。这篇文章也有很棒的教程
cybmeta'1

Answers:


10

让我们一步一步地走。看起来您只是在尝试使用OAuth进行身份验证,但在这样做之前,您需要获取访问令牌该令牌将在进行API调用时用于进行身份验证。

由于这使用的是OAuth版本1,为了获取访问令牌,您必须执行以下操作:

  1. 首先,设置一个应用程序,调用该站点,以使用该应用程序的客户端ID和密码获取请求令牌(临时凭证)
  2. 第二,从第一步开始,调用站点以使用请求令牌对应用程序进行授权(面向用户,请参见下文)。
  3. 第三,完成授权后,您可以致电该站点以获取访问令牌(现在该应用程序已被授权)

我建议在前几个步骤中使用Postman,因为它们只需完成一次即可。Postman还将处理timestampnonce和的生成oauth signature,因此,如果您不使用OAuth库,则应绝对使用Postman。一旦你有你的访问令牌,你可以通过卷曲没有任何库的调用。

https://www.getpostman.com/

第一步(设置应用程序)

安装WP OAuth 1插件,激活,然后转到“ 用户”>“应用程序”下的菜单项。添加新的应用程序,填写名称和描述。对于回调,URL会将用户重定向到(授权后),或者oop带外流将重定向到显示验证者令牌的内部页面(而不是重定向)。

https://github.com/WP-API/OAuth1/blob/master/docs/basics/Registering.md

要继续第二步,需要使用创建的应用程序中的客户端ID客户端密钥对您的站点进行呼叫,以获取临时凭据(请求令牌)。

打开Postman,创建新呼叫http://website.com/oauth1/request,单击Authorization选项卡,从下拉列表中选择OAuth 1.0,在Client Key,Client Secret中输入,将签名方法设置为HMAC-SHA1,启用将参数添加到标头,对oauth签名进行编码,然后单击Update Request

邮递员OAuth1请求

邮递员将自动为您生成签名,随机数和时间戳,并将其添加到标题(您可以在“标题”选项卡下查看)。

单击发送,您将收到包含oauth_token和的响应oauth_token_secret邮递员OAuth1请求响应

这些值将用于下一步,以WordPress用户帐户授权应用程序。

第二步(授权申请)

授权步骤只需要完成一次,这一步骤是面向用户的,并且是每个人都熟悉的步骤。由于您使用的是OAuth1,因此该步骤是必需的,并且该应用程序需要与WordPress用户帐户相关联。想想一个网站何时允许您使用Facebook登录……他们将您定向到您登录的Facebook并单击“授权”……这需要通过WordPress网站来完成。

我建议您将Web浏览器用于此步骤,因为您可以轻松地在URL中设置变量,这将提供“授权”页面来授权应用程序。

打开您的Web浏览器,然后输入网站的URL,如下所示: http://website.com/oauth1/authorize

现在添加到该URL,oauth_consumer_key(客户端ID)oauth_tokenoauth_token_secret(来自上一步)。在我的示例中,这是完整的URL:

http://website.com/oauth1/authorize?oauth_consumer_key=TUPFNj1ZTd8u&oauth_token=J98cN81p01aqSdFd9rjkHZWI&oauth_token_secret=RkrMhw8YzXQljyh99BrNHmP7phryUvZgVObpmJtos3QExG1O

OAuth1授权应用

单击授权后,您将看到另一个带有验证令牌的屏幕。在我的示例中,这是返回的验证令牌E0JnxjjYxc32fMr2AF0uWsZm

第三步(获取访问令牌)

现在,我们已经授权了该应用程序,我们需要进行最后一个调用以获取授权令牌,该令牌将用于进行所有API调用。就像第一步我要使用Postman一样(因为签名必须是HMAC-SHA1),它使完成这些步骤的难度提高了100倍。

再次打开Postman,然后将URL更改为 http://website.com/oauth1/access

确保添加令牌和令牌密钥(第一步中的值),然后单击“ 参数”以显示URL下方的框。在左侧输入oauth_verifier,然后在右侧输入第二步中的代码,即验证令牌

邮递员OAuth1访问步骤

确保单击“更新请求”,然后单击“发送”,您应该使用oauth_token和来返回响应oauth_token_secret……这就是进行API调用所需要的!丢弃步骤1中的原始文件,将其保存在代码中或其他安全的地方。

邮递员OAuth1访问响应

然后,您可以对您的站点进行API调用,并使用返回的令牌和令牌密钥设置标头。

您可以通过Authorization标头,GET参数或POST(如果编码为application / x-www-form-urlencoded)通过多种方式传递。请记住,您必须传递签名,时间戳和随机数。我不知道这个回复会花多长时间,所以明天我将用示例对您的代码进行更新,以进行更新。

我强烈建议安装Rest API日志,以便您可以查看API调用的日志,并查看发送,返回的​​内容等。这将极大地帮助调试。

https://github.com/petenelson/wp-rest-api-log


我知道,有许多使用Postman或类似工具的教程,但是我找不到任何可以使用CURL功能完成整个过程的教程,我的意思是纯PHP代码。这就是我想要的。
MinhTri

@ Dan9 TBH实际上是不可能的……至少对于OAuth1来说不是,主要是因为您必须使用用户帐户来授权应用程序。使用CURL可以轻松完成所有其他步骤,问题在于使用CURL以WordPress用户身份登录(这意味着您需要将凭据存储在PHP文件中,这不是一个好主意),并且需要对应用程序进行授权可以修改OAuth1代码库,但老实说,如果您想使用CURL来做所有事情……您正在以错误的方式思考,应该提出另一种解决方案或方法。
sMyles

@ Dan9与您要执行的操作一样,您应该使用OAuth2服务器而不是OAuth1,这主要是因为OAuth2具有包括“客户端凭据”授予类型在内的新功能,从而避免了执行所有这些步骤bshaffer.github.io / oauth2-server-php-docs / grant-types /…
sMyles

@ Dan9如果您100%准备使用CURL通过OAuth1获得帮助,我确实认为有可能发生一些代码黑客攻击,但是正如我提到的,这意味着您必须保存用户的USERNAME和PASSWORD到PHP文件。如果您对此感到满意,请告诉我,让我不满意使用CURL编写了一个教程来使用它,如果您打算使用OAuth2,或者不想再使用它,则不想花时间编写教程
sMyles

@ Dan9好...就这样...如果您要使用OAuth1,则必须关联一个WordPress用户帐户。基本上将访问令牌想像成API密钥……“ API密钥”必须与用户帐户关联……现在,是否使用您设置的标准帐户由您决定..但是无论何时使用OAuth1,必须与用户帐户相关联,因此获取访问令牌的过程很漫长。
sMyles

2

将其添加为另一个答案可为您提供帮助,帮助您确定如何执行此操作。基本上如我的评论所述,如果您要使用OAuth1,则必须将其与用户帐户相关联,否则就无法解决。

首先,您需要使用CURL使用WordPress的用户名密码登录网站,存储cookie,以便可以在对OAuth的CURL调用中使用它(确保更新您的CURL调用以包含cookie):

/programming/724107/wordpress-autologin-using-curl-or-fsockopen-in-php

然后使用带有客户端ID和客户端密钥的CURL调用OAuth,以获取临时的oauth令牌和密钥(请求令牌)

要进行此调用(以及获取访问令牌的调用),您需要正确设置CURL调用。有关代码和参考,请参见此答案的结尾。

获得临时的oauth令牌和密钥(请求令牌)后,请对您的网站的URL进行CURL POST调用:

http://website.com/oauth1/authorize

然后,您需要从返回的HTML中提取授权页面的所有值,然后将您自己的POST提交到表单操作URL。

/programming/35363815/how-to-get-a-value-input-from-html-returned-of-curl

具体来说,这些必须包含在您的POST数据中才能完成“授权” POST到 http://domain.com/wp-login.php?action=oauth1_authorize

  • _wpnonce -这是要提交的表单的现时值,必须从HTML输入中提取该值并与POST一起提交

    consumer -这是HTML中的隐藏输入(这是对帖子ID的引用,因此您必须从HTML输入中拉出它

    oauth_token -这是HTML中的隐藏输入(但您也应该已经有此输入)

    wp-submit -这需要设置为值 authorize

这是为身份验证页面生成的示例HTML:

<form name="oauth1_authorize_form" id="oauth1_authorize_form" action="http://website.com/wp-login.php?action=oauth1_authorize" method="post">

    <h2 class="login-title">Connect My Auth</h2>

    <div class="login-info">
        <p>Howdy <strong>admin</strong>,<br/> "My OAuth Demo" would like to connect to Example Site.</p>

    </div>

    <input type="hidden" name="consumer" value="5428" /><input type="hidden" name="oauth_token" value="i1scugFXyPENniCP4kABKtGb" /><input type="hidden" id="_wpnonce" name="_wpnonce" value="ca9b267b4f" /><input type="hidden" name="_wp_http_referer" value="/wp-login.php?action=oauth1_authorize&amp;oauth_consumer_key=TUPFNj1ZTd8u&amp;oauth_token=i1scugFXyPENniCP4kABKtGb&amp;oauth_token_secret=gzqW47pHG0tilFm9WT7lUgLoqN2YqS6tFFjUEiQoMgcmG2ic" />   <p class="submit">
        <button type="submit" name="wp-submit" value="authorize" class="button button-primary button-large">Authorize</button>
        <button type="submit" name="wp-submit" value="cancel" class="button button-large">Cancel</button>
    </p>

</form>

在使用所有这些值/数据进行POST之后,这就是将随授权代码一起返回的HTML(因此您需要从代码<code>块内部提取值:

<div id="login">
    <h1><a href="https://wordpress.org/" title="Powered by WordPress" tabindex="-1">Example Site</a></h1>
    <p>Your verification token is <code>yGOYFpyawe8iZmmcizqVIw3f</code></p> <p id="backtoblog"><a href="http://website.com/">&larr; Back to Example Site</a></p>
</div>

获得验证令牌后,您就可以/oauth1/access使用验证令牌,oauth令牌和oauth令牌密钥进行调用。验证令牌需要放在POST数据中,如下所示:oauth_verifier

这将返回您的新的永久访问令牌和VOILA!

示例CURL代码

以下是进行CURL调用的示例代码,其中最重要的部分是如何oauth_signature生成:

https://oauth1.wp-api.org/docs/basics/Signing.html

function buildBaseString($baseURI, $method, $params){
    $r = array();
    ksort($params);
    foreach($params as $key=>$value){
        $r[] = "$key=" . rawurlencode($value);
    }

    return $method."&" . rawurlencode($baseURI) . '&' . rawurlencode(implode('&', $r));
}

function buildAuthorizationHeader($oauth){
    $r = 'Authorization: OAuth ';
    $values = array();
    foreach($oauth as $key=>$value)
        $values[] = "$key=\"" . rawurlencode($value) . "\"";

    $r .= implode(', ', $values);
    return $r;
}

// Add request, authorize, etc to end of URL based on what call you're making
$url = "http://domain.com/oauth/";

$consumer_key = "CLIENT ID HERE";
$consumer_secret = "CLIENT SECRET HERE";

$oauth = array( 'oauth_consumer_key' => $consumer_key,
                'oauth_nonce' => time(),
                'oauth_signature_method' => 'HMAC-SHA1',
                'oauth_callback' => 'oob',
                'oauth_timestamp' => time(),
                'oauth_version' => '1.0');

$base_info = buildBaseString($url, 'GET', $oauth);
$composite_key = rawurlencode($consumer_secret) . '&' . rawurlencode($oauth_access_token_secret);
$oauth_signature = base64_encode(hash_hmac('sha1', $base_info, $composite_key, true));
$oauth['oauth_signature'] = $oauth_signature;


$header = array(buildAuthorizationHeader($oauth), 'Expect:');
$options = array( CURLOPT_HTTPHEADER => $header,
                  CURLOPT_HEADER => false,
                  CURLOPT_URL => $url,
                  CURLOPT_RETURNTRANSFER => true,
                  CURLOPT_SSL_VERIFYPEER => false);

$feed = curl_init();
curl_setopt_array($feed, $options);
$json = curl_exec($feed);
curl_close($feed);

$return_data = json_decode($json);

print_r($return_data);

这个网站确切地告诉您如何编码OAuth签名,以及如何使用CURL发送(我建议阅读整个页面):https : //hannah.wf/twitter-oauth-simple-curl-requests-for-your-own-数据/

有关生成OAuth1签名的更多资源:https ://stackoverflow.com/questions/24613277/oauth-signature-generation-using-hmac-sha1

其他资源:http : //collaboradev.com/2011/04/01/twitter-oauth-php-tutorial/


如何获得客户ID和客户机密并将其与有效用户相关联?当前,只有管理员可以创建新应用,并且只能通过管理控制台进行。顺便说一句,我已经尝试oauth_signature按照您的指示进行生成,但是无论如何,响应总是json_oauth1_signature_mismatch
MinhTri'9

@ Dan9是的,是的,管理员必须创建应用程序,否则这将是一个巨大的安全问题,允许匿名用户创建应用程序。这是一些有关签名wordpress.stackexchange.com/questions/185511/… 的网站。github.com/ WP
API

0

更新:从我阅读的内容来看,您需要进行多次卷曲来获取access_token,然后使用它进行查询

  • 临时凭证获取:客户端从服务器获取一组临时凭证。
  • 授权:用户“授权”请求令牌访问其帐户。
  • 令牌交换:客户端将短期的临时凭证交换为长期的令牌。

oauth1服务器流


0

我知道我来晚了一点,但是可以使用wp_remote_get和_post吗?

我正在使用它们在我的wordpress安装中拉出并发布内容:

这是来自wordpress Codex的一般想法:

$response = wp_remote_post( $url, array(
    'body'    => $data,
    'httpversion' => '1.0',
    'sslverify' => false,
    'headers' => array(
        'Authorization' => 'Basic ' . base64_encode( $username . ':' . $password ),
    ),
) );

这是一个更具体的示例:

$url='http://WWW.EXAMPLE HERE.';
$response = wp_remote_post( $url, array(
    'method' => 'POST',
    'timeout' => 45,
    'redirection' => 5,
    'httpversion' => '1.0', //needed to get a response
    'blocking' => true,
    'headers' => array('Authorization' => 'Basic ' . base64_encode( 'MY TOKENID' . ':' . '' )),
    'body' => $body // in array
    'cookies' => array()
    )
);

if ( is_wp_error( $response ) ) {
   $error_message = $response->get_error_message();
   echo "Something went wrong: $error_message";
} else {
 //  echo 'Response:<pre>';
 //  print_r( $response );
 //    echo '</pre>'; 
$responseBody = json_decode($response['body'],true);
echo $responseBody['message'];

    }
    }
}

诀窍是对用户名和密码进行编码。现在,时间通常取决于API用户名,而pw将为空白或作为您的令牌。

因此,例如在上面的特定示例中,标题为

'headers' => array('Authorization' => 'Basic ' . base64_encode( 'MYTOKENID' . ':' . '' ))

我把pw空白。这取决于您使用的API系统。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.