vzool/api-hmac-guard

该软件包最新版本(v4.2.10)没有可用的许可证信息。

使用Laravel通过API HMAC密钥简单安全地验证API的简单方法

v4.2.10 2018-05-10 07:38 UTC

README

Latest Stable Version Total Downloads Join the chat at https://gitter.im/chrisbjr/api-guard

Impersonate Protection Algorithm

使用Laravel通过API HMAC密钥简单安全地验证API的简单方法。此软件包使用了以下库

现在支持Laravel 5.3、5.4和5.5!

**Laravel 5.3.x及以后版本:~4.*

**Laravel 5.1.x至5.2.x:~3.*

**Laravel 5.1.x:~2.*

**Laravel 4.2.x:~1.*(为Laravel 4更新的最近版本。请注意,这里有一些命名空间的变化)

**Laravel 4.2.x:0.*(你们大多数人使用的版本)

分支概述要点

1- API令牌绝不应存储在数据库中,这有助于我们保护用户令牌,防止在发生数据泄露时通过泄露的数据库令牌冒充用户账户。

2- 数据库将保存一个public_key,这是一个访问密钥对记录的端点,此密钥应该是唯一的并建立索引。

3- 数据库将保存一个private_key,该密钥将在服务器端保持私密。

4- 每次请求发生时,都会生成一个作为shared_key的令牌。

5- 令牌将通过Hmac生成,并使用应用程序密钥config('app.key')作为服务器私钥,与private_key一起,在服务器端被视为客户端私钥。

6- 默认的Hmac算法是sha3-384,有许多算法可供选择这里

7- 如果您更改Hmac算法,密钥长度将不同,这取决于算法本身。

8- Middleware将期望作为标题的两个密钥,它们是

  • X-Auth-EndPoint:这是一个public_key
  • X-Auth-Token:这是一个shared_key

9- 如果您不喜欢默认的标题名称,则可以从中更新它们apiguard.php配置文件。

10- 您应该将这些两个密钥public_keyshared_key发送给您的客户端,并让他们将其发送回服务器以进行身份验证。

快速示例

>>> $key = ApiKey::make($person); // or $user
=> Vzool\ApiHmacGuard\Models\ApiKey {#1256
     public_key: "-15af2b946b069d-5mQykkuMmF8UDZIuZkG8AdFfB3udhYkGW-",
     apikeyable_id: 1,
     apikeyable_type: "App\Models\Person",
     last_ip_address: "127.0.0.1",
     last_used_at: Carbon\Carbon @1525856582 {#1263
       date: 2018-05-09 12:03:02.723851 Asia/Riyadh (+03:00),
     },
     private_key: "-17AKPqotjcQBjzmdktluKiR5qUbyyzqWov-15af2b946b0c4-",
     updated_at: "2018-05-09 12:03:02",
     created_at: "2018-05-09 12:03:02",
     id: 5,
   }
>>> $key->clientKeys()
=> [
     "endpoint" => "-15af2b946b069d-5mQykkuMmF8UDZIuZkG8AdFfB3udhYkGW-",
     "token" => "9f9de38c4405a747fc25dd146b2ee6a30e8ea627c7da26d5a616c4c2fcb9ec896b4020febcb4971a65b97959c5d5625a",
   ]
>>> 
>>> $key->publicKey()
=> "-15af2b946b069d-5mQykkuMmF8UDZIuZkG8AdFfB3udhYkGW-"
>>> $key->sharedKey()
=> "9f9de38c4405a747fc25dd146b2ee6a30e8ea627c7da26d5a616c4c2fcb9ec896b4020febcb4971a65b97959c5d5625a"
>>> $key->privateKey()
=> null // private keys are always protected and writable for one time

快速开始

Laravel 5.3到5.4的安装

运行composer require vzool/api-hmac-guard 4.*

在您的config/app.php中,将Vzool\ApiHmacGuard\Providers\ApiGuardServiceProvider添加到providers数组末尾

'providers' => array(

    ...
    Vzool\ApiHmacGuard\Providers\ApiGuardServiceProvider::class,
),

现在发布api-guard的迁移和配置文件

$ php artisan vendor:publish --provider="Vzool\ApiHmacGuard\Providers\ApiGuardServiceProvider"

然后运行迁移

$ php artisan migrate

它将设置api_keys表。

生成您的第一个API密钥

完成所需设置后,您现在可以生成第一个API密钥。

运行以下命令生成API密钥

php artisan api-key:generate

通常,ApiKey对象是一个多态对象,这意味着它可以属于多个其他模型。

要生成与另一个对象(例如“用户”)相关联的API密钥,您可以执行以下操作

+php artisan api-key:generate --id=1 --type="App\User"

要指定模型可以具有API密钥,可以将Apikeyable特征附加到模型

use Vzool\ApiHmacGuard\Models\Mixins\Apikeyable;

class User extends Model
{
    use Apikeyable;

    ...
}

这将向模型附加以下方法

// Get the API keys of the object
$user->apiKeys();

// Create an API key for the object
$user->createApiKey();

在您的应用内部生成API密钥,您可以在ApiKey模型中使用以下方法

$apiKey = Vzool\ApiHmacGuard\Models\ApiKey::make()

// Attach a model to the API key
$apiKey = Vzool\ApiHmacGuard\Models\ApiKey::make($model)

访问客户端密钥

$apiKey->clientKeys()

用法

您只需将auth.apikey中间件附加到您的API路由即可开始使用ApiGuard

Route::middleware(['auth.apikey'])->get('/test', function (Request $request) {
    return $request->user(); // Returns the associated model to the API key
});

这实际上通过需要指定在X-Authorization头中的API密钥来保护您的API。这可以在config/apiguard.php中进行配置。

以下是一个示例cURL命令以进行演示

curl -X GET \
  http://apiguard.dev/api/test \
  -H 'x-authorization: api-key-here'

您还可能希望将此中间件附加到您的app/Http/Kernel.php中的api中间件组中,以利用Laravel的其他功能,例如限流。

/**
 * The application's route middleware groups.
 *
 * @var array
 */
protected $middlewareGroups = [
    ...

    'api' => [
        'throttle:60,1',
        'bindings',
        'auth.apikey',
    ],
];

如果在基本示例中您已经注意到,您还可以通过调用$request->user()来访问附加到API密钥的模型。我们之所以在此方法中附加相关模型,是因为在大多数情况下,这实际上是用户。

未经授权的请求

未经授权的请求将收到包含以下JSON的401状态响应

{
  "error": {
    "code": "401",
    "http_code": "GEN-UNAUTHORIZED",
    "message": "Unauthorized."
  }
}

ApiGuardController

ApiGuardController利用了Fractalapi-response库。

这使我们能够轻松创建带有模型和使用转换器以提供标准化JSON响应的API。

以下是一个示例

假设您有以下模型

use Illuminate\Database\Eloquent\Model;

class Book extends Model
{
    protected $fillable = [
        'name',
    ];
}

您可以创建一个基本的控制器,它将返回所有书籍,如下所示

use Vzool\ApiHmacGuard\Http\Controllers\ApiGuardController;
use App\Transformers\BookTransformer;
use App\Book;

class BooksController extends ApiGuardController
{
    public function all()
    {
        $books = Book::all();

        return $this->response->withCollection($books, new BookTransformer);
    }
}

现在,您需要为您的Book对象创建转换器。转换器有助于定义和操作您希望返回到JSON响应中的变量。

use League\Fractal\TransformerAbstract;
use App\Book;

class BookTransformer extends TransformerAbstract
{
    public function transform(Book $book)
    {
        return [
            'id'         => $book->id,
            'name'       => $book->name,
            'created_at' => $book->created_at,
            'updated_at' => $book->updated_at,
        ];
    }
}

一旦您在路由中可以访问它,您将从这个控制器获得以下响应

{
  "data": {
    "id": 1,
    "title": "The Great Adventures of Chris",
    "created_at": {
      "date": "2017-05-25 18:54:18",
      "timezone_type": 3,
      "timezone": "UTC"
    },
    "updated_at": {
      "date": "2017-05-25 18:54:18",
      "timezone_type": 3,
      "timezone": "UTC"
    }
  }
}

更多示例可以在GitHub页面找到:[https://github.com/ellipsesynergie/api-response](https://github.com/ellipsesynergie/api-response)

要了解更多关于转换器的信息,请访问PHP League关于Fractal的文档:[http://fractal.thephpleague.com/](http://fractal.thephpleague.com/)

API验证响应

ApiGuard附带一个请求类,可以为您处理请求验证并抛出标准响应。

您可以像平常一样创建一个Request类,但要获得标准JSON响应,您必须扩展ApiGuardFormRequest类。

use Vzool\ApiHmacGuard\Http\Requests\ApiGuardFormRequest;

class BookStoreRequest extends ApiGuardFormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'name' => 'required',
        ];
    }
}

现在您可以在控制器中使用它,就像您通常在Laravel中那样

use Vzool\ApiHmacGuard\Http\Controllers\ApiGuardController;
use App\Transformers\BookTransformer;
use App\Book;

class BooksController extends ApiGuardController
{
    public function store(BookStoreRequest $request)
    {
        // Request should already be validated

        $book = Book::create($request->all())

        return $this->response->withItem($book, new BookTransformer);
    }
}

如果请求未能通过验证规则,它将返回如下响应

{
  "error": {
    "code": "GEN-UNPROCESSABLE",
    "http_code": 422,
    "message": {
      "name": [
        "The name field is required."
      ]
    }
  }
}