mfrost503 / snaggle
OAuth 1.0 客户端库
Requires
- php: >=5.4.0
Requires (Dev)
- phpunit/phpunit: ~4.4
- squizlabs/php_codesniffer: ~2.1
This package is auto-updated.
Last update: 2024-09-12 09:16:36 UTC
README
Snaggle 是一个 OAuth 1 客户端库,可以用来生成签名和适当的 OAuth 1 标头。虽然建议使用 OAuth 2.0 来构建新的 API,但仍有大量流行的服务使用 OAuth 1.0。
安装
Snaggle 应该通过 composer 进行安装
"require": {
"mfrost503/snaggle": "1.0.0"
}
OAuth 1.0 客户端示例
OAuth 1.0 需要使用访问和消费者令牌,能够创建有效的签名将解锁 OAuth 1.0 API 的内容。
use Snaggle\OAuth1\Client\Credentials\AccessCredentials; use Snaggle\OAuth1\Client\Credentials\ConsumerCredentials; use Snaggle\OAuth1\Client\Signatures\HmacSha1; use Snaggle\OAuth1\Client\Signatures\Plaintext; use Snaggle\OAuth1\Client\Header\Header; // first we need to represent our tokens, these should be stored securely $consumer = new ConsumerCredentials('CONSUMER_KEY', 'CONSUMER_SECRET'); $access = new AccessCredentials('ACCESS_TOKEN', 'ACCESS_SECRET'); $signature = new HmacSha1($consumer, $access) ->setResourceURL('https://api.example.com/v1/users') ->setHttpMethod('get'); $header = new Header(); $header->setSignature($signature); $header->createAuthorizationHeader();
还有一种明文签名类型(仅在无其他选择且通过 https 时使用),它实现了签名接口并使用签名父类,因此其使用方式与 HmacSha1 相同,只是实例化方式不同。
$signature = new Plaintext($consumer, $access);
此行可以与前面示例中的签名实例化互换使用。
签名
此库实现了 HMAC-SHA1 和明文签名,这些签名用于传达发起请求的资源所有者的身份。服务可能会有不同的要求来构建签名,此库中的签名是根据 OAuth 1.0 规范构建的。
HMAC-SHA1
HMAC-SHA1 是此库中两种签名类型中更安全的一种,也是最常用的。此签名涉及创建一个基础字符串和组合密钥,它们封装并散列出 OAuth 1.0 服务所需的标识信息。
明文
明文签名仅在 https 上使用,因为它们不安全。像 Twitter 这样的服务不允许你使用明文签名,但如果你在与内部 API 一起工作且签名的复杂性不会提供真正的安全优势,它们可以非常方便。
HTTP 客户端
Snaggle 库中没有包含 HTTP 客户端,原因是已经有一些做得非常好的 HTTP 客户端,但每个人的需求和访问这些工具的方式可能不同。这些客户端在其预期任务上做得很好,即发送 HTTP 请求。Snaggle 在此过程中的角色是提供使 OAuth 1 请求正常工作的必要标头,并将这些标头传递给选择的任何客户端。
在向客户端提供标头时存在几种不同的情况。例如,在设置 cURL 中的标头时,你必须发送 'Authorization: '
前缀,但与 Guzzle 一起,你只需要标头的具体内容。Snaggle 提供了生成带有或不带有前缀的标头的选项。以下是使用 Guzzle 和 cURL 的示例。
Guzzle
在 Guzzle 中,我们不需要前缀,因此 $header->creationAuthorizationHeader()
有一个参数 $includePrefix
,默认设置为 false。因此,以下是使用不需要标头前缀的客户端的方法。
$header = new Header(); $header->setSignature($signature); $authorizationHeader = $header->createAuthorizationHeader(); $client = new Client(); $client->get('https://api.example.com/v1/users', [ 'headers' => ['Authorization' => $authorizationHeader] ]);
cURL
cURL 在向请求添加标头时需要前缀。为此,我们只需将参数 true
传递给 $header->createAuthorizationHeader();
即可。
$header = new Header(); $header->setSignature($signature); $authorizationHeader = $header->createAuthorizationHeader(true); $ch = curl_init('https://api.example.com/v1/users'); curl_setopt($ch, CURLOPT_HTTPHEADER, [$authorizationHeader]);
使用这种方法,我们可以将 OAuth 1 标头的生成与最终用于发送请求的 HTTP 客户端解耦。
制作令牌请求
理解起来更具挑战性的一点是令牌交换,这是与资源服务器通信所必需的。本质上,需要在不同的时间进行一些来回通信。以下是一个示例,说明如何使用这个库从Twitter获取访问令牌。
use \Snaggle\Client\Credentials\ConsumerCredentials; use \Snaggle\Client\Credentials\AccessCredentials; use \Snaggle\Client\Signatures\HmacSha1; use \Snaggle\Client\Header\Header; use \GuzzleHttp\Client; $consumer = new ConsumerCredentials('CONSUMER KEY', 'CONSUMER_SECRET'); $access = new AccessCredentials(); if (!isset($_GET['oauth_token']) && !isset($_GET['oauth_verifier'])) { $signature = new HmacSha1($consumer, $access); $signature->setResourceURL('https://api.twitter.com/oauth/request_token') ->setHttpMethod('post'); $headers = new Header(); $headers->setSignature($signature); $auth = $headers->createAuthorizationHeader(); $client = new Client(); $response = $client->post('https://api.twitter.com/oauth/request_token', [ 'headers' => ['Authorization' => $auth] ]); $res = $response->getBody(); parse_str($res); header('Location: https://api.twitter.com/oauth/authorize?oauth_token=' . $oauth_token); } else if(isset($_GET['oauth_token']) && isset($_GET['oauth_verifier'])) { $access = new AccessCredentials($_GET['oauth_token']); $signature = new HmacSha1($consumer, $access); $signature->setHttpMethod('post') ->setResourceURL('https://api.twitter.com/oauth/access_token'); $headers = new Header(); $headers->setSignature($signature); $auth = $headers->createAuthorizationHeader(); $client = new Client(); $response = $client->post('https://api.twitter.com/oauth/access_token', [ 'headers' => ['Authorization' => $auth], 'body' => ['oauth_verifier' => $_GET['oauth_verifier']] ]); $res = $response->getBody(); // parse_str will create variables called $oauth_token and $oauth_token_secret parse_str($res); $token = $oauth_token; $secret = $oauth_token_secret; // You will need to persist these values at this point }
注意事项
OAuth 1.0可能一开始看起来有些难以理解,这个库的目标是封装很多这种困惑,并提供一个简单的接口来执行OAuth 1.0调用。在构建这个库时,考虑到的是OAuth 1.0 RFC标准,但我觉得我应该指出,并不是自称OAuth 1.0服务的每个服务都遵循这个标准。
这个库与试图紧密遵循OAuth 1.0规范中的签名标准的API表现最佳,不幸的是,这意味着这可能与自称OAuth 1.0的每个API都不兼容。这并不意味着我们完全放弃这些API,只是意味着随着我们越来越了解它们,我们将不得不分析是否为了这个项目的最佳利益而适应各种与OAuth 1.0标准的偏差。欢迎提交Pull Requests。