欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

Dingo + Laravel + JWT + Entrust + memcache 实现API设计

Dingo + Laravel + JWT + Entrust + memcache 实现API设计

Dingo Api 是一个为laravel设计的用于API开发的开源包,规范和简化了Api的设计

JWT 即 Json Web Token,是一种新的用于API认证方式,区别于传统的Session和Cookie方式,便于携带而且比较安全,因为token只设计为单次请求

Entrust 是一套基于角色的权限管理系统,用于分层系统设计

Memcache 是一个NoSQL存储系统,使用键值对将数据存储在内存中,实现快速访问

DingoApi 安装及使用

https://github.com/dingo/api

  1. 安装
//项目基本目录下执行
composer require dingo/api:1.0.x@dev
//config/app.php
'providers' => [
    Dingo\Api\Provider\LaravelServiceProvider::class
]
//发布配置文件
php artisan vendor:publish --provider="Dingo\Api\Provider\LaravelServiceProvider"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  1. 配置
//配置可以卸载.env文件中或者config/api.php
API_STANDARDS_TREE=vnd //api 标准
API_SUBTYPE=myapp  //项目短名称
API_PREFIX=api
API_DOMAIN=api.myapp.com   //这里记住API_PREFIX或者API_DOMAIN通知只能配置一个,或的关系,访问的时候通过 http://127.0.0.1:8000/api/your_route 或者 http://api.myapp.com/your_route
API_VERSION=v1
API_NAME="My API" //在.env文件中一定要注意不能有多余的空格,负责出现莫名的错误,如果写成API_NAME=My API就会出错
API_CONDITIONAL_REQUEST=false 
API_STRICT=false //如果配置为真,将需要在每次访问api是添加Accept头:application/vnd.myapp.v1+json
API_DEFAULT_FORMAT=json //api返回格式
API_DEBUG=true //API调试
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  1. 认证方式

认证方式我们采用JWT方式,关于JWT可以自行谷歌,其他的配置请参考dingo/api 文档

'auth' => [
        'jwt' => 'Dingo\Api\Auth\Provider\JWT',
    ],
  • 1
  • 2
  • 3

JWT认证方式

https://github.com/tymondesigns/jwt-auth

  1. 安装
composer require "tymon/jwt-auth:0.5.*"
//添加服务
'Tymon\JWTAuth\Providers\JWTAuthServiceProvider'
//添加alias
JWTAuth' => 'Tymon\JWTAuth\Facades\JWTAuth'
//发布配置文件
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"
//生成jwt:key
php artisan jwt:generate
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  1. 配置,请参考文档,没什么好说的
  2. 创建token

token可以基于任何传入的数据创建,不过我们一般使用从用户创建token,如:

$user = User::first();

$token = JWTAuth::fromUser($user);
  • 1
  • 2
  • 3

这里具体的流程是,用户提交认证数据,然后根据提交数据查询用户,得到用户以后创建token,这里贴一段我的代码

public function signIn(Request $request)
    {
        $info = (new SignInForm())->load($request, 'sign-in');
        if($info instanceof Response)
        {
            return $info;
        }

        $user = null;

        if(Auth::attempt(['nick_name' => $request->input('identity'), 'password' => $request->input('password'), 'status' => User::STATUS_NORMAL])
           || Auth::attempt(['email' => $request->input('identity'), 'password' => $request->input('password'), 'status' => User::STATUS_NORMAL])
           || Auth::attempt(['mobile' => $request->input('identity'), 'password' => $request->input('password'), 'status' => User::STATUS_NORMAL] ))
        {
            $user = Auth::user();
        }

       if($user)
       {
           $token = JWTAuth::fromUser($user);
       } else {
           return ApiResponse::apiResponse(ResponseCode::SIGN_IN_FAILED);
       }

        return ApiResponse::apiResponse(ResponseCode::SIGN_IN_OK, [
            'token' => $token
        ], 0);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

客户端在收到token以后,在需要认证api中加入Authorization头: Authorization:Bearer {token},我们在dingo/api中配值了API使用jwt认证,所以我们在我们的路由中添加jwt中间件:

//routes.php
<?php

//这里使用的web组中间件中,我只是开启了session,其他的都已经注释掉了,尤其是CSRF中间件应该去掉,否则每次还要提交CSRF值,也可以单独设置session
// 'web' => [
//             //\App\Http\Middleware\EncryptCookies::class,
//             //\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
//             \Illuminate\Session\Middleware\StartSession::class,
//             //\Illuminate\View\Middleware\ShareErrorsFromSession::class,
//             //\App\Http\Middleware\VerifyCsrfToken::class,
//         ],

$api = app('Dingo\Api\Routing\Router');
$api->version('v1', function ($api){

    $api->group(['namespace' => 'App\Http\Controllers\V1', 'middleware' => ['web']], function ($api){

        $api->post('sign-up', ['as' => 'user.signUp', 'uses' => 'AppController@signUp']);
        $api->post('sign-in', ['as' => 'user.signIn', 'uses' => 'AppController@signIn']);
        $api->post('third-auth', ['as' => 'user.thirdAuth', 'uses' => 'AppController@thirdAuth']);
        $api->post('password-reset/send-verify-code', 'PasswordController@sendResetPasswordEmail');
        $api->post('password-reset/set-new-password', 'PasswordController@resetNewPassword');

        $api->group(['middleware' => 'api.auth'], function ($api){

            $api->group(['middleware' => ['before' => 'jwt.auth']], function ($api){

                $api->group(['middleware' => ['after' => 'jwt.refresh']], function ($api){

                    //用户资源
                    $api->resource('user', 'UserController', [
                        'only' => ['show', ],
                        'names' => [
                            'show' => 'user.show',
                        ],
                    ]);

                    //用户资料资源
                    $api->resource('profile', 'ProfileController', [
                        'only' => ['show', ],
                        'names' => [
                            'show' => 'profile.show'
                        ],
                    ]);

                });

                $api->get('logout', ['as' => 'user.logout', 'uses' => 'AppController@logout']);
                $api->get('refresh-token', ['as' => 'user.refreshToken', 'uses' => 'AppController@refreshToken']);
            });
        });

    });
});

api.auth中间件不要配置,只是说明路由是保护路由;

jwt.auth 需要配置,配置请看文档,会在api请求处理之前检查用户是否已经认证,主要是验证Authorization头部信息;

jwt.refresh 会在访问成功之后,刷新token,并附加在响应头部的Authorization头部中;但是这个中间件应该只能用于需连续访问的API中,像logout和refresh-token就不需要刷新。
说到刷新token,如果大家了解jwt认证机制,应该明白token只能用于单次请求,请求成功之后失效,不过可以通过这个旧的token刷新得到新的token;
因此这里要启用黑名单功能,将失效的token写入黑名单。黑名单十一缓存的形式存在,根据应用缓存的配置,写入文件或者数据库或者其他形式,如果是写入文件,你的storage目录应该要具有可写权限;

需要提醒的是缓存形式配置为file时,entrust不能正常使用,此问题需等待新版本修复。折中的办法是你可以将缓存设置memcached,就不会出现问题了
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64

entrust

https://github.com/Zizaco/entrust

关于entrust本人觉得除了缓存配置比较坑意外,其他应该都能看得懂,有问题请留言

ubuntu memcached 服务器以及PHP扩展库安装:

  1. memcached 服务器安装
//方法一:
sudo apt-get install memcached
//方法二(编译安装):
wget http://memcached.org/files/memcached-1.4.25.tar.gz
tar xzvf memcached-1.4.25.tar.gz
cd memcached-1.4.25
./configure && make && make test && sudo make install
//最后测试
memcached -d -m 50 -p 11211 -u root
-m 指定使用多少兆的缓存空间;-p 指定要监听的端口; -u 指定以哪个用户来运行 -d 以系统进程运行,也就是作为系统服务
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  1. 安装libmmecached
wget https://launchpad.net/libmemcached/1.0/0.51/+download/libmemcached-0.51.tar.gz
tar xzvf libmemcached-0.51.tar.gz
cd libmemcached-0.51
 ./configure  --prefix=/usr/local/libmemcached --with-memcached
sudo make && sudo make install
  • 1
  • 2
  • 3
  • 4
  • 5
  1. 安装memcached扩展库
//安装之前可能要求安装pkg-config
sudo apt-get install phk-config
wget http://pecl.php.net/get/memcached-2.2.0.tgz
tar xzvf memcached-2.2.0.tgz
cd memcached-2.2.0
phpize5
/configure  --with-php-config=/usr/bin/php-config --with-libmemcached-dir=/usr/local/libmemcached --enable-memcached --disable-memcached-sasl
sudo make && sudo make install
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  1. memadmin memcached监控工具 
    https://github.com/junstor/memadmin

需要PHPmemcache扩展

来自  http://blog.csdn.net/gamelife1314/article/details/51498808

普通分类: