awalko/api-guard 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

awalko/api-guard

Composer 安装命令:

composer require awalko/api-guard

包简介

A simple way of authenticating your APIs with API keys using Laravel

README 文档

README

A simple way of authenticating your APIs with API keys using Laravel. This package uses the following libraries:

The concept for managing API keys is also taken from Phil Sturgeon's codeigniter-restserver. I've been looking for an equivalent for Laravel but did not find any so this is an implementation for that.

Quick start

Required setup

In the require key of composer.json file add the following

"awalko/api-guard": "dev-master"

Run the Composer update comand

$ composer update

In your config/app.php add 'Awalko\ApiGuard\ApiGuardServiceProvider' to the end of the $providers array

'providers' => array(

    'Illuminate\Foundation\Providers\ArtisanServiceProvider',
    'Illuminate\Auth\AuthServiceProvider',
    ...
    'EllipseSynergie\ApiResponse\Laravel\ResponseServiceProvider',
    'Awalko\ApiGuard\ApiGuardServiceProvider',

),

Now generate the api-guard migration (make sure you have your database configuration set up correctly):

$ php artisan migrate --package="awalko/api-guard"

It will setup two tables - api_keys and api_logs.

Generating your first API key

Once you're done with the required setup, you can now generate your first API key.

Make sure your Laravel installation is accessible through a web server - if not, you can use artisan to quickly bring up your Laravel installation by running the command below:

$ php artisan serve

Once the web server is up, you can issue a POST request ApiGuard's pre-defined route for generating an API key. You can use curl in the command line as shown below:

$ curl -X POST http://localhost:8000/apiguard/api_key

This will generate an API key and should return the following data:

{
    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"
        }
    }
}

Take note of your first API key.

Now, to prevent others from generating API keys through the route above, you can disable this in ApiGuard's configuration file.

To create your own configuration file for ApiGuard, run the following command:

$ php artisan config:publish awalko/api-guard

The configuration file will be found in app/config/packages/awalko/api-guard/config.php. Open this file and change the generateApiKeyRoute variable to false

'generateApiKeyRoute' => false

Generally, you will want to generate API keys for each user in your application. The api_keys table has a user_id field which you can populate for your users.

Usage

Basic usage of ApiGuard is to create a controller and extend that class to use the 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();
        }
    }
}

Notice the $apiMethods variable. You can set limitss , levels, and keyAuthentication for each method here. If you don't specify any, the defaults would be that no limits would be implemented, no level access, and key authentication would be required.

You should also be able to use the api-response object by using $this->response. More examples can be found on the Github page: https://github.com/ellipsesynergie/api-response.

You can access the above controller by creating a basic route in your app/routes.php:

Route::get('api/v1/books', 'BooksController@all');
Route::get('api/v1/books/{id}', 'BooksController@show');

You will need to use your API key and put it in the header to access it. By default, the header value is using the Authorization parameter. You can change this in the config file.

Try calling this route using curl

 curl --header "Authorization: 2ed9d72e5596800bf805ca1c735e446df72019ef" http://localhost:8000/api/v1/books

You should get the following response:

{
    "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
    }
}

Accessing the User instance and Stateless authentication

You can easily access the User instance from the belongsTo() relationship of the ApiKey model to the User class. With this, we can implement API based authentication with the following as an example.

Note that while we have utilized Confide for handling the credential checking, you can have your own way of having this done (like using the native Laravel Auth class, or Sentry for that matter).

<?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'
            ]
        ]);
    }
}

awalko/api-guard 适用场景与选型建议

awalko/api-guard 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 52 次下载、GitHub Stars 达 7, 最近一次更新时间为 2014 年 11 月 14 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「json」 「rest」 「api」 「laravel」 「api keys」 「api authentication」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 awalko/api-guard 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 awalko/api-guard 我们能提供哪些服务?
定制开发 / 二次开发

基于 awalko/api-guard 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 52
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 7
  • 点击次数: 13
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 7
  • Watchers: 1
  • Forks: 141
  • 开发语言: PHP

其他信息

  • 授权协议: Unknown
  • 更新时间: 2014-11-14