我正在尝试将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>


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

// 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
        )
)


我该如何运作?谢谢。

评论

事情并不是那么容易。我一直在尝试写答案,但时间很长。您可以先阅读文档,尤其是“授权流程”。这篇文章也有很棒的教程。

#1 楼

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

因为它使用的是OAuth版本1,所以要获取访问令牌,您必须执行以下操作:


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

我建议使用Postman作为前几步,因为它们只需完成一次即可。 Postman还将处理生成timestampnonceoauth signature,因此,如果您不使用OAuth库,则绝对应该使用Postman。获得访问令牌后,您就可以通过CURL进行呼叫,而无需任何库。

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的新调用,单击“授权”选项卡,从下拉列表中选择OAuth 1.0,在“客户端密钥”,“客户端机密”中输入,将签名方法设置为HMAC-SHA1,启用在标头中添加参数,对oauth签名进行编码,然后单击更新请求



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

单击“发送”,您将收到包含oauth_tokenoauth_token_secret的响应:


这些值将在下一步中用于在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




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

第三步(获取访问令牌)

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

再次打开Postman并进行更改http://website.com/oauth1/access的URL

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



确保单击更新请求,然后单击发送,并且您应该使用oauth_tokenoauth_token_secret返回响应...这就是进行API调用所需要的!丢弃步骤1中的原始代码,然后将这些代码保存在您的代码中或其他安全的地方。



然后您可以对站点进行API调用,设置标头

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

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

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

评论


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

– SarahCoding
16-09-20在8:30



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

–迈尔斯
16-09-20在15:01

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

–迈尔斯
16-09-20在15:14

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

–迈尔斯
16-09-20在15:16

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

–迈尔斯
16-09-20在15:57

#2 楼

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

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

https://stackoverflow.com/questions/ 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。

https ://stackoverflow.com/questions/35363815/how-to-get-a-value-input-from-html-returned-of-curl

尤其是这些都需要包含在POST数据中完成“授权”过帐到http://domain.com/wp-login.php?action=oauth1_authorize



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

consumer-这是HTML中的隐藏输入(这是对Post 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>


获得验证令牌后,就可以使用验证令牌,oauth令牌和oauth令牌密钥来调用/oauth1/access。验证令牌需要以oauth_verifier的形式放入POST数据
这将返回您的新永久访问令牌和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-data /

有关生成OA的更多资源uth1签名:
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。

– SarahCoding
16-09-21在3:49



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

–迈尔斯
16-09-21在17:55

#3 楼

我知道我来晚了一点,但是您可以使用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系统。

#4 楼

更新:根据我的阅读,您需要进行多次卷曲才能获得access_token,然后使用它进行查询


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

oauth1服务器流