acquia/http-hmac-php

PHP 实现的 HTTP HMAC 规范,集成了诸如 Symfony 和 Guzzle 等流行的库。


README

Build Status Total Downloads Latest Stable Version License

该库实现了 HTTP HMAC 规范 的 2.0 版本,用于对 RESTful Web API 请求进行签名和验证。它可以与流行的框架和库,如 Symfony 和 Guzzle 集成,并且可以在服务器和客户端上使用。

安装

使用 Composer 并将其添加到项目 composer.json 文件中的依赖项

{
    "require": {
        "acquia/http-hmac-php": "^5.0"
    }
}

有关更详细的安装和使用说明,请参阅 Composer 文档

使用

使用 Guzzle 发送的 API 请求签名

require_once 'vendor/autoload.php';

use Acquia\Hmac\Guzzle\HmacAuthMiddleware;
use Acquia\Hmac\Key;
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;

// Create the HTTP HMAC key.
// A key consists of and ID and a Base64-encoded shared secret.
// Note: the API provider may have already encoded the secret. In this case, it should not be re-encoded.
$key_id = 'e7fe97fa-a0c8-4a42-ab8e-2c26d52df059';
$key_secret = base64_encode('secret');
$key = new Key($key_id, $key_secret);

// Optionally, you can provide additional headers when generating the signature.
// The header keys need to be provided to the middleware below.
$headers = [
    'X-Custom-1' => 'value1',
    'X-Custom-2' => 'value2',
];

// Specify the API's realm.
// Consult the API documentation for this value.
$realm = 'Acquia';

// Create a Guzzle middleware to handle authentication during all requests.
// Provide your key, realm and the names of any additional custom headers.
$middleware = new HmacAuthMiddleware($key, $realm, array_keys($headers));

// Register the middleware.
$stack = HandlerStack::create();
$stack->push($middleware);

// Create a client.
$client = new Client([
    'handler' => $stack,
]);

// Request.
try {
    $result = $client->get('https://service.acquia.io/api/v1/widget', [
        'headers' => $headers,
    ]);
} catch (ClientException $e) {
    print $e->getMessage();
    $response = $e->getResponse();
}
  
print $response->getBody();

使用 PSR-7 兼容的请求进行请求认证

use Acquia\Hmac\RequestAuthenticator;
use Acquia\Hmac\ResponseSigner;

// $keyLoader implements \Acquia\Hmac\KeyLoaderInterface
$authenticator = new RequestAuthenticator($keyLoader);

// $request implements PSR-7's \Psr\Http\Message\RequestInterface
// An exception will be thrown if it cannot authenticate.
$key = $authenticator->authenticate($request);

$signer = new ResponseSigner($key, $request);
$signedResponse = $signer->signResponse($response);

使用 Symfony 的安全组件进行认证

为了使用提供的 Symfony 集成,您需要在项目的 composer.json 中包含以下可选库

{
    "require": {
        "symfony/psr-http-message-bridge": "~0.1",
        "symfony/security": "~3.0",
        "zendframework/zend-diactoros": "~1.3.5"
    }
}

示例实现

# app/config/parameters.yml
parameters:
   hmac_keys: {"key": "secret"}

# app/config/services.yml
services:
    hmac.keyloader:
        class: Acquia\Hmac\KeyLoader
        arguments:
            $keys: '%hmac_keys%'

    hmac.request.authenticator:
        class: Acquia\Hmac\RequestAuthenticator
        arguments:
         - '@hmac.keyloader'
        public: false
        
    hmac.response.signer:
        class: Acquia\Hmac\Symfony\HmacResponseListener
        tags:
          - { name: kernel.event_listener, event: kernel.response, method: onKernelResponse }
          
    hmac.entry-point:
        class: Acquia\Hmac\Symfony\HmacAuthenticationEntryPoint

    hmac.security.authentication.provider:
        class: Acquia\Hmac\Symfony\HmacAuthenticationProvider
        arguments:
            - '@hmac.request.authenticator'
        public: false

    hmac.security.authentication.listener:
        class: Acquia\Hmac\Symfony\HmacAuthenticationListener
        arguments: ['@security.token_storage', '@security.authentication.manager', '@hmac.entry-point']
        public: false

# app/config/security.yml
security:
    # ...

    firewalls:
        hmac_auth:
            pattern:   ^/api/
            stateless: true
            hmac_auth: true
// src/AppBundle/AppBundle.php
namespace AppBundle;

use Acquia\Hmac\Symfony\HmacFactory;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class AppBundle extends Bundle
{
    public function build(ContainerBuilder $container)
    {
        parent::build($container);
        $extension = $container->getExtension('security');
        $extension->addSecurityListenerFactory(new HmacFactory());
    }
}

使用 HMAC HTTP 认证在 Symfony 中测试控制器使用 PHPUnit

  1. 添加服务声明
# app/config/parameters_test.yml

services:
    test.client.hmac:
        class: Acquia\Hmac\Test\Mocks\Symfony\HmacClient
        arguments: ['@kernel', '%test.client.parameters%', '@test.client.history', '@test.client.cookiejar']
// src/AppBundle/Tests/HmacTestCase.php

namespace MyApp\Bundle\AppBundle\Tests;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Client;
use Acquia\Hmac\Key;

class HmacTestCase extends WebTestCase
{
    /**
     * @var Client
     */
    private $client;

    protected static function createClient(array $options = array(), array $server = array())
    {
        $kernel = static::bootKernel($options);

        $client = $kernel->getContainer()->get('test.client.hmac');
        $client->setServerParameters($server);

        return $client;
    }

    protected function setUp()
    {
        $this->client = static::createClient();

        $this->client->setKey(new Key('my-key', 'my-not-really-secret'));
    }

贡献和开发

GNU MakeComposer 用于管理开发依赖和测试

# Install depdendencies
make install

# Run test suite
make test

所有代码应遵循以下标准

使用 GitHub 的标准 pull request 工作流程提交更改。