awalko / api-guard
使用Laravel通过API密钥简单验证您的API
Requires
- php: >=5.4.0
- ellipsesynergie/api-response: 0.7.*
- illuminate/database: *
- illuminate/support: 4.2.*
- league/fractal: 0.9.*
This package is not auto-updated.
Last update: 2024-09-24 08:06:32 UTC
README
使用Laravel通过API密钥简单验证您的API。本软件包使用了以下库
- philsturgeon的 Fractal
- maximebeaudoin的 api-response
管理API密钥的概念也来自Phil Sturgeon的 codeigniter-restserver。我一直寻找Laravel的等效方案,但没有找到,因此这是一个针对该方案的实现。
快速开始
必需设置
在composer.json
文件的require
键中添加以下内容
"awalko/api-guard": "dev-master"
运行Composer更新命令
$ composer update
在您的config/app.php
中,将'Awalko\ApiGuard\ApiGuardServiceProvider'
添加到$providers
数组的末尾
'providers' => array(
'Illuminate\Foundation\Providers\ArtisanServiceProvider',
'Illuminate\Auth\AuthServiceProvider',
...
'EllipseSynergie\ApiResponse\Laravel\ResponseServiceProvider',
'Awalko\ApiGuard\ApiGuardServiceProvider',
),
现在生成api-guard迁移(确保您已正确设置数据库配置)
$ php artisan migrate --package="awalko/api-guard"
它将设置两个表 - api_keys 和 api_logs。
生成您的第一个API密钥
完成必需设置后,您现在可以生成第一个API密钥。
确保您的Laravel安装可以通过Web服务器访问 - 如果不行,您可以使用artisan
通过运行以下命令快速启动Laravel安装
$ php artisan serve
一旦Web服务器启动,您可以通过向ApiGuard预定义的路由发送POST请求来生成API密钥。您可以在命令行中使用curl
,如下所示
$ curl -X POST https://:8000/apiguard/api_key
这将生成一个API密钥,并返回以下数据
{
data: {
id: 9
user_id: 0
key: "7f03891b8f7c4ba10af2e0e37232f98fa2fc9a1a"
level: 10
ignore_limits: 1
created_at: {
date: "2014-06-26 12:07:49"
timezone_type: 3
timezone: "UTC"
}
updated_at: {
date: "2014-06-26 12:07:49"
timezone_type: 3
timezone: "UTC"
}
}
}
请注意您的第一个API密钥。
现在,为了防止其他人通过上述路由生成API密钥,您可以在ApiGuard的配置文件中禁用此功能。
要为ApiGuard创建自己的配置文件,请运行以下命令
$ php artisan config:publish awalko/api-guard
配置文件将在app/config/packages/awalko/api-guard/config.php
中找到。打开此文件,将generateApiKeyRoute
变量更改为false
'generateApiKeyRoute' => false
通常,您会希望为您的应用程序中的每个用户生成API密钥。在api_keys
表中有一个user_id
字段,您可以为您用户填充该字段。
用法
ApiGuard的基本用法是创建一个控制器,并扩展该类以使用ApiGuardController
。
<?php
use Awalko\ApiGuard\ApiGuardController;
class BooksController extends ApiGuardController
{
protected $apiMethods = [
'all' => [
'keyAuthentication' => true,
'level' => 1,
'limits' => [
// The variable below sets API key limits
'key' => [
'increment' => '1 hour',
'limit' => 100
],
// The variable below sets API method limits
'method' => [
'increment' => '1 day',
'limit' => 1000
]
]
],
'show' => [
'keyAuthentication' => false
]
];
public function all()
{
$books = Book::all();
return $this->response->withCollection($books, new BookTransformer);
}
public function show($id)
{
try {
$book = Book::findOrFail($id);
return $this->response->withItem($book, new BookTransformer);
} catch (ModelNotFoundException $e) {
return $this->response->errorNotFound();
}
}
}
注意$apiMethods
变量。您可以为每个方法设置limits
、levels
和keyAuthentication
。如果您没有指定任何,则默认不实施限制、无级别访问和需要密钥认证。
您还可以通过使用$this->response
来使用api-response对象。更多示例可以在GitHub页面上找到:https://github.com/ellipsesynergie/api-response。
您可以通过在app/routes.php
中创建基本路由来访问上述控制器
Route::get('api/v1/books', 'BooksController@all');
Route::get('api/v1/books/{id}', 'BooksController@show');
您需要使用您的API密钥,并将其放入标题中才能访问。默认情况下,标题值使用Authorization
参数。您可以在配置文件中更改此值。
尝试使用curl
调用此路由
curl --header "Authorization: 2ed9d72e5596800bf805ca1c735e446df72019ef" https://:8000/api/v1/books
您应该得到以下响应
{
"data": {
"id": 1,
"title": "The Great Adventures of Chris",
"created_at": {
"date": "2014-03-25 18:54:18",
"timezone_type": 3,
"timezone": "UTC"
},
"updated_at": {
"date": "2014-03-25 18:54:18",
"timezone_type": 3,
"timezone": "UTC"
},
"deleted_at": null
}
}
访问User实例和无状态认证
您可以从ApiKey模型与User类之间的belongsTo()关系轻松访问User实例。利用这一点,我们可以实现以下示例中的基于API的认证。
请注意,虽然我们使用了Confide来处理凭证检查,但您可以选择自己的方式来完成这一任务(例如使用Laravel的内置Auth类,或者使用Sentry)。
<?php
namespace api\v1;
use Awalko\ApiGuard\ApiGuardController;
use Awalko\ApiGuard\ApiKey;
use Awalko\ApiGuard\Transformers\ApiKeyTransformer;
use Confide;
use Input;
use User;
use Validator;
class UserApiController extends ApiGuardController
{
protected $apiMethods = [
'authenticate' => [
'keyAuthentication' => false
]
];
public function authenticate() {
$credentials['username'] = Input::json('username');
$credentials['password'] = Input::json('password');
$validator = Validator::make([
'username' => $credentials['username'],
'password' => $credentials['password']
],
[
'username' => 'required|max:255',
'password' => 'required|max:255'
]
);
if ($validator->fails()) {
return $this->response->errorWrongArgsValidator($validator);
}
try {
$user = User::whereUsername($credentials['username'])->first();
$credentials['email'] = $user->email;
} catch (\ErrorException $e) {
return $this->response->errorUnauthorized("Your username or password is incorrect");
}
if (Confide::logAttempt($credentials) == false) {
return $this->response->errorUnauthorized("Your username or password is incorrect");
}
// We have validated this user
// Assign an API key for this session
$apiKey = ApiKey::where('user_id', '=', $user->id)->first();
if (!isset($apiKey)) {
$apiKey = new ApiKey;
$apiKey->user_id = $user->id;
$apiKey->key = $apiKey->generateKey();
$apiKey->level = 5;
$apiKey->ignore_limits = 0;
} else {
$apiKey->generateKey();
}
if (!$apiKey->save()) {
return $this->response->errorInternalError("Failed to create an API key. Please try again.");
}
// We have an API key.. i guess we only need to return that.
return $this->response->withItem($apiKey, new ApiKeyTransformer);
}
public function getUserDetails() {
$user = $this->apiKey->user;
return isset($user) ? $user : $this->response->errorNotFound();
}
public function deauthenticate() {
if (empty($this->apiKey)) {
return $this->response->errorUnauthorized("There is no such user to deauthenticate.");
}
$this->apiKey->delete();
return $this->response->withArray([
'ok' => [
'code' => 'SUCCESSFUL',
'http_code' => 200,
'message' => 'User was successfuly deauthenticated'
]
]);
}
}