awalko/api-guard

该软件包最新版本(v0.5)没有提供许可信息。

使用Laravel通过API密钥简单验证您的API

v0.5 2014-10-18 02:24 UTC

This package is not auto-updated.

Last update: 2024-09-24 08:06:32 UTC


README

使用Laravel通过API密钥简单验证您的API。本软件包使用了以下库

管理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变量。您可以为每个方法设置limitslevelskeyAuthentication。如果您没有指定任何,则默认不实施限制、无级别访问和需要密钥认证。

您还可以通过使用$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'
            ]
        ]);
    }
}