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

这里的技术是共享的

You are here

用 Laravel 搭建带 OAuth2 oauth oauth2.0 2.0 验证的 RESTful 服务 有大用 有大用

用 Laravel 搭建带 OAuth2 验证的 RESTful 服务


 

原文请看我的博客: 用Laravel搭建带Oauth2验证的RESTful服务

Github源码请看这里: Laravel-RESTful-Service

参考了 Laravel 5 token based Authentication (OAuth 2.0) & Dingo Wiki,但是原文中有一些bug,而且不适用最新的5.2版本,我的教程里解决了这些问题。

1.全新安装Laravel并配置好你的数据库,我在这里用的是mysql.#

composer global require "laravel/installer"
laravel new restful

2.修改 composer.json 并在命令行运行 composer update 添加两个包.#

    "require": {
        "php": ">=5.5.9",
        "laravel/framework": "5.2.*",
        //下面这两个是新添加的,注意版本号
        "dingo/api": "1.0.*dev",
        "lucadegasperi/oauth2-server-laravel": "5.1.*"
    }

换句话说 就是执行:  
composer.bat require dingo/api:1.0.x@dev 
composer.bat require lucadegasperi/oauth2-server-laravel

3.在 config/app.php 文件里添加新的 providers.#

<?php
    'providers' => [

        //Add bottom lines to your providers array.
        /**
         * Customized Service Providers...
          */
//本来原文少了这个App\Providers\OAuthServiceProvider::class, 
//出现access_token验证不通过 会报下面的错 ,详细的错见本网页的最后//"message": "Failed to authenticate because of bad credentials or an invalid authorization header.",
        App\Providers\OAuthServiceProvider::class, 
        Dingo\Api\Provider\LaravelServiceProvider::class,
        LucaDegasperi\OAuth2Server\Storage\FluentStorageServiceProvider::class,
        LucaDegasperi\OAuth2Server\OAuth2ServerServiceProvider::class,

    ],

在 aliases 里添加下面的内容:#

<?php
    'aliases' => [

        //Add bottom lines to your aliases array.
        'Authorizer' => LucaDegasperi\OAuth2Server\Facades\Authorizer::class,

    ],

4.在你的 app/Http/Kernel.php 文件里添加新的 $middleware & $routeMiddleware.#

<?php
    protected $middleware = [
        //Add bottom lines to your $middleware array.
        \LucaDegasperi\OAuth2Server\Middleware\OAuthExceptionHandlerMiddleware::class,
    ];
    //
    protected $routeMiddleware = [
        //Add bottom lines to your $routeMiddleware array.
        'oauth' => \LucaDegasperi\OAuth2Server\Middleware\OAuthMiddleware::class,
        'oauth-user' => \LucaDegasperi\OAuth2Server\Middleware\OAuthUserOwnerMiddleware::class,
        'oauth-client' => \LucaDegasperi\OAuth2Server\Middleware\OAuthClientOwnerMiddleware::class,
        'check-authorization-params' => \LucaDegasperi\OAuth2Server\Middleware\CheckAuthCodeRequestMiddleware::class,
    ];

5.在你的项目里运行 php artisan vendor:publish & php artisan migrate .#

添加这些配置项在 .env 文件里,具体含义可以查看Dingo Wiki:#

API_STANDARDS_TREE=x
API_SUBTYPE=rest
API_NAME=REST
API_PREFIX=api
API_VERSION=v1
API_CONDITIONAL_REQUEST=true
API_STRICT=false
API_DEBUG=true
API_DEFAULT_FORMAT=json

配置你的 app\config\oauth2.php 文件:#

<?php
    //Modify the $grant_types as follow.
    'grant_types' => [
            'password' => [
             'class' => 'League\OAuth2\Server\Grant\PasswordGrant',
             'access_token_ttl' => 604800,

             // the code to run in order to verify the user's identity
             'callback' => 'App\Http\Controllers\VerifyController@verify',
             ],
        ],

6.在 routes.php 文件添加我们需要的路由.#


<?php
//Add the following lines to your routes.php

/**
 * OAuth
 */

//Get access_token
Route::post('oauth/access_token', function() {
 return Response::json(Authorizer::issueAccessToken());
});

//Create a test user, you don't need this if you already have.
Route::get('/register',function(){$user = new App\User();
 $user->name="tester";
 $user->email="test@test.com";
 $user->password = \Illuminate\Support\Facades\Hash::make("password");
 $user->save();
});

/**
 * Api
 */
$api = app('Dingo\Api\Routing\Router');

//Show user info via restful service.
$api->version('v1', ['namespace' => 'App\Http\Controllers'], function ($api) {
    $api->get('users', 'UsersController@index');
    $api->get('users/{id}', 'UsersController@show');
});

//Just a test with auth check.
$api->version('v1', ['middleware' => 'api.auth'] , function ($api) {
    $api->get('time', function () {
        return ['now' => microtime(), 'date' => date('Y-M-D',time())];
    });
});

7.在数据库的 oauth_client 表里添加一条 client 数据用来测试. 例如phphub就是github API的一个client#

INSERT INTO `oauth_clients` (`id`, `secret`, `name`, `created_at`, `updated_at`) VALUES
(f3d259ddd3ed8ff3843839b,4c7f6f8fa93d59c45502c0ae8c4a95b, ‘Main website’,20150512 21:00:00,00000000 00:00:00);

8.编写你的 API Controller.#

随便叫什么 Book,Post,User 都好,这是一个举例:

<?php

namespace App\Http\Controllers;

use App\User;
use App\Http\Controllers\Controller;

class UsersController extends Controller
{

    public function index()
    {
        return User::all();
    }

    public function show($id)
    {
        return User::findOrFail($id);
    }
}

9.开始测试吧!#

其实已经初步完工了,接下来我们要测试刚才配置好的服务,一般会用到一个Chrome应用 PostMan 来模拟请求你的服务器,当然你也可以用自己的办法.

GET from ServerOauth2Token test

 本帖已被设为精华帖!
 
 
 
 

 
回复数量: 28
  •  
    discountry
    #1 ⋅ 1年前

    今天折腾了一下午终于搭好了,和大家分享一下 BTW…App端的编辑有Bug呀

  •  
    linlance
    #4 ⋅ 1年前

    介绍一下优点吧?看着头晕脑胀。。。laravel不是自己就有原生的验证端了么?

  •  
    discountry
    #5 ⋅ 1年前

    这个是拿laravel做RESTful API服务时候用的,不是咱们的CMS网站登录验证,当然要拿来做登录验证也不是不可以…

  •  
    kenneth 极客地图创始人
    #6 ⋅ 1年前

    非常棒的教程,而且还是L5.2 App\Http\Controllers\VerifyController@verify 这里面要写点啥?

  •  
    kenneth 极客地图创始人
    #7 ⋅ 1年前

    @linlance L5.2的原生验证?api_token=这种还是没有Oauth2这种安全,我个人理解。

  •  
    kenneth 极客地图创始人
    #8 ⋅ 1年前

    @discountry 我能得到access_token,但是后面一个用access_token请求接口不行。

    {"message":"Failed to authenticate because of bad credentials or an invalid authorization header.","status_code":401,"debug"

    可能是什么原因导致,无法通过认证呢?

  •  
    ilvsx
    #9 ⋅ 1年前

    @kenneth 添加 Header Authorization : Bearer PjqswJA1n47h03m1wseO0KAoZAf0yChgbgcfJMjz

    PjqswJA1n47h03m1wseO0KAoZAf0yChgbgcfJMjz 就是 access_token

  •  
    kenneth 极客地图创始人
    #10 ⋅ 1年前
    curl http://localhost:8000/api/user/1 -H 'Authorization: Bearer AG24h4DdMU8z7SKl1r3O8iXQRs169Wi06OIwd4VS'

    这个我知道,但是我加了'middleware' => 'api.auth'就报错,认证过不去,不知道为啥?

  •  
    ilvsx
    #11 ⋅ 1年前

    @kenneth 用 xdebug 调试看看吧,不然只能靠猜……

  •  
    kenneth 极客地图创始人
    #12 ⋅ 1年前

    @ilvsx 好的,我自己排查一下。 @discountry 你怎么可以直接获取到数据?

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

    我是说这个加了api.auth这个的,其他都OK的

  •  
    msjack
    #13 ⋅ 1年前

    oauth2.0现在好多大型网站都在用

  •  
    discountry
    #14 ⋅ 1年前

    @kenneth 最后的token是直接从url传过去的,不在header里

  •  
    discountry
    #15 ⋅ 1年前

    @kenneth 看我路由里的写法,api的路由和laravel的router是分开写的

  •  
    haoning747
    #17 ⋅ 1年前

    不错不错,哥用jsp写了个站:http://www.quzhuanpan.com 发现php更加简洁有力,谢谢楼主,受教了。

  •  
    kenneth 极客地图创始人
    #18 ⋅ 1年前

    @haoning747 你是在做SEO?

    @discountry 放header和url传access_token是一样的。但是我试了接口,还是不行。不加'middleware' => 'api.auth'才能请求,说明这个认证过不去,不知道为什么?

  •  
    hye
    #19 ⋅ 1年前

    https://laravel.com/docs/5.2/upgrade#upgrade-5.2.0

    MySQL Dates

    Starting with MySQL 5.7, 0000-00-00 00:00:00 is no longer considered a valid date, since strict mode is enabled by default.

    小处不注意也是小坑啊

    请问,PHP版的 Oauth server效率怎么样?

  •  
     
     
  •  
    kenneth 极客地图创始人
    #23 ⋅ 1年前

    @discountry 好的,我阅读一下,自己先排查一下原因,有没有联系方式,我们好交流交流?给我邮件吧。@Summer 希望能有一个站内信功能。

  •  
    kenneth 极客地图创始人
    #24 ⋅ 1年前

    @discountry 经过我仔细的比对,我发现我少了这个文件,加上后OK了

    App\Providers\OAuthServiceProvider::class,

    这个文件不知道什么时候生成的呢? 这个有大用 

  •  
    camry 系统架构师 & 前端工程师
    #25 ⋅ 1年前
  •  
    kenneth 极客地图创始人
    #26 ⋅ 1年前

    @camry 感谢提醒,以后一定要仔细读文档。

  •  
    flyinging
    #27 ⋅ 11个月前

    @discountry 搭起来了,如果token失效了怎么刷新token或者重新生成token?

  •  
    Nicksxs
    #28 ⋅ 5个月前

    TokenMismatchException 楼主我碰到了这个问题,不知道应该怎么解决,麻烦看下,谢谢

 

{
    "message": "Failed to authenticate because of bad credentials or an invalid authorization header.",
    "status_code": 401,
    "debug": {
        "line": 113,
        "file": "D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\dingo\\api\\src\\Auth\\Auth.php",
        "class": "Symfony\\Component\\HttpKernel\\Exception\\UnauthorizedHttpException",
        "trace": [
            "#0 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\dingo\\api\\src\\Auth\\Auth.php(96): Dingo\\Api\\Auth\\Auth->throwUnauthorizedException(Array)",
            "#1 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\dingo\\api\\src\\Http\\Middleware\\Auth.php(52): Dingo\\Api\\Auth\\Auth->authenticate(Array)",
            "#2 [internal function]: Dingo\\Api\\Http\\Middleware\\Auth->handle(Object(Dingo\\Api\\Http\\Request), Object(Closure))",
            "#3 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(136): call_user_func_array(Array, Array)",
            "#4 [internal function]: Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Dingo\\Api\\Http\\Request))",
            "#5 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Pipeline.php(32): call_user_func(Object(Closure), Object(Dingo\\Api\\Http\\Request))",
            "#6 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\dingo\\api\\src\\Http\\Middleware\\PrepareController.php(45): Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Dingo\\Api\\Http\\Request))",
            "#7 [internal function]: Dingo\\Api\\Http\\Middleware\\PrepareController->handle(Object(Dingo\\Api\\Http\\Request), Object(Closure))",
            "#8 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(136): call_user_func_array(Array, Array)",
            "#9 [internal function]: Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Dingo\\Api\\Http\\Request))",
            "#10 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Pipeline.php(32): call_user_func(Object(Closure), Object(Dingo\\Api\\Http\\Request))",
            "#11 [internal function]: Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Dingo\\Api\\Http\\Request))",
            "#12 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(103): call_user_func(Object(Closure), Object(Dingo\\Api\\Http\\Request))",
            "#13 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(726): Illuminate\\Pipeline\\Pipeline->then(Object(Closure))",
            "#14 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(699): Illuminate\\Routing\\Router->runRouteWithinStack(Object(Illuminate\\Routing\\Route), Object(Dingo\\Api\\Http\\Request))",
            "#15 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(675): Illuminate\\Routing\\Router->dispatchToRoute(Object(Dingo\\Api\\Http\\Request))",
            "#16 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\dingo\\api\\src\\Routing\\Adapter\\Laravel.php(81): Illuminate\\Routing\\Router->dispatch(Object(Dingo\\Api\\Http\\Request))",
            "#17 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\dingo\\api\\src\\Routing\\Router.php(513): Dingo\\Api\\Routing\\Adapter\\Laravel->dispatch(Object(Dingo\\Api\\Http\\Request), 'v1')",
            "#18 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\dingo\\api\\src\\Http\\Middleware\\Request.php(126): Dingo\\Api\\Routing\\Router->dispatch(Object(Dingo\\Api\\Http\\Request))",
            "#19 [internal function]: Dingo\\Api\\Http\\Middleware\\Request->Dingo\\Api\\Http\\Middleware\\{closure}(Object(Dingo\\Api\\Http\\Request))",
            "#20 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(150): call_user_func(Object(Closure), Object(Dingo\\Api\\Http\\Request))",
            "#21 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\lucadegasperi\\oauth2-server-laravel\\src\\Middleware\\OAuthExceptionHandlerMiddleware.php(36): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Dingo\\Api\\Http\\Request))",
            "#22 [internal function]: LucaDegasperi\\OAuth2Server\\Middleware\\OAuthExceptionHandlerMiddleware->handle(Object(Dingo\\Api\\Http\\Request), Object(Closure))",
            "#23 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(136): call_user_func_array(Array, Array)",
            "#24 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\CheckForMaintenanceMode.php(44): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Dingo\\Api\\Http\\Request))",
            "#25 [internal function]: Illuminate\\Foundation\\Http\\Middleware\\CheckForMaintenanceMode->handle(Object(Dingo\\Api\\Http\\Request), Object(Closure))",
            "#26 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(136): call_user_func_array(Array, Array)",
            "#27 [internal function]: Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Dingo\\Api\\Http\\Request))",
            "#28 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(103): call_user_func(Object(Closure), Object(Dingo\\Api\\Http\\Request))",
            "#29 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\dingo\\api\\src\\Http\\Middleware\\Request.php(127): Illuminate\\Pipeline\\Pipeline->then(Object(Closure))",
            "#30 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\dingo\\api\\src\\Http\\Middleware\\Request.php(103): Dingo\\Api\\Http\\Middleware\\Request->sendRequestThroughRouter(Object(Dingo\\Api\\Http\\Request))",
            "#31 [internal function]: Dingo\\Api\\Http\\Middleware\\Request->handle(Object(Illuminate\\Http\\Request), Object(Closure))",
            "#32 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(136): call_user_func_array(Array, Array)",
            "#33 [internal function]: Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}(Object(Illuminate\\Http\\Request))",
            "#34 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Pipeline.php(32): call_user_func(Object(Closure), Object(Illuminate\\Http\\Request))",
            "#35 [internal function]: Illuminate\\Routing\\Pipeline->Illuminate\\Routing\\{closure}(Object(Illuminate\\Http\\Request))",
            "#36 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(103): call_user_func(Object(Closure), Object(Illuminate\\Http\\Request))",
            "#37 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php(132): Illuminate\\Pipeline\\Pipeline->then(Object(Closure))",
            "#38 D:\\xampputf8\\htdocs\\laravelOauth\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php(99): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter(Object(Illuminate\\Http\\Request))",
            "#39 D:\\xampputf8\\htdocs\\laravelOauth\\public\\index.php(54): Illuminate\\Foundation\\Http\\Kernel->handle(Object(Illuminate\\Http\\Request))",
            "#40 {main}"
        ]
    }
}
普通分类: