2016年9月1日 星期四

[Laravel 5.3 新功能] 11. Laravel Passport 介绍

说明

此文章是 [Laravel 5.3 新功能] 系列的第十一篇文章,Laravel Passport 介绍。
[Laravel 5.3 新功能] 系列完整文章列表请见:https://phphub.org/topics/2638

注意事项

在编写此文章时,Passport 还未正式发布,因此可能会和发布版本有所出入。我会在其正式发布后第一时间更新此文章。

什么是 Laravel Passport

API 的身份验证是我们开发中最棘手的部分。OAuth 是你可以考虑的比较严格的验证方式,但是它比较难集成。我们曾经有讨论过使用多个路由、migration、复杂的配置等等来简化身份验证的集成难度,但实际上集成此服务还是过于复杂。
不过,在 5.3 以后出现了 Laravel Passport,它是一个为 Laravel 提供原生 OAuth 2 服务的组件。类似于 Cashier 和 Scout,你可通过 Composer 将其安装到你的 Laravel 应用程序中,而且它集成非常简单。

Laravel 5.2 中身份认证的弊端

在 Laravel 5.2 里,我们利用多目录来为身份认证提供多个 auth 认证服务,这意味着你可以在不同的环境中使用不同的身份认证方式(如 web 和 api,或者生产环境和开发环境)。
在 5.2 中,默认的 token 的身份验证机制已经足够使用了,但是它对于需要登录操作的业务来说不够安全,所以我们需要 passport 来提供更安全的 OAuth2 认证机制。

安装 Passport

1)、运行下面的命令,通过 Composer 安装 Passport
composer require laravel/passport
2)、打开你的 config/app.php 文件,将 Laravel\Passport\PassportServiceProvider 添加到 $providers 属性中。
3)、运行 migrations
php artisan migrate
4)、打开你的 User 类,并引入 Laravel\Passport\HasApiTokens traits。
5)、在你的 AuthServiceProvider 文件中引入 use Laravel\Passport\Passport,然后在 boot() 方法中添加 OAuth2 路由方法 Passport::routes()
// AuthServiceProvider
public function boot()
{
    Passport::routes();
}
6)、 加入 Passport::tokensCan() 方法
// AuthServiceProvider
public function boot()
{
    Passport::route();
    Passport::tokensCan([
        'conference' => 'Access your conference information'
    ]);
}
7)、在 config/auth.php 文件中,修改 guards.api.driver 配置,将 driver 设置为 passport
// config/auth.php
return [
    ...
    'guards' => [
        ...
        'api' => [
            'driver' => 'passport', // was previously 'token'
            'provider' => 'users'
        ]
    ]
];
这样就全部配置成功了,非常简单吧。接下来将讲解如何管理你的客户端和 token。

Passport 如何管理 API

Passport 通过 JSON 格式的 API 提供服务给客户端,这些 API 都提供了管理(新增、删除等)客户端和个人 token 的方法。
Passport 默认使用 Vue 组件来展示你的 API,你可以使这个组件来展示和管理你的 API。当然,你也可以编写自定义的工具来集成 API。

Passport 默认使用 Vue 框架

Passport 使用了三个 Vue 组件:

<passport-clients></passport-clients>


<passport-authorized-clients></passport-authorized-clients>


<passport-personal-access-tokens></passport-personal-access-tokens>
我们来分析一下它们都做了什么。
在 Laracon 上,Taylor 做了一个例子。他先在 http://passport.dev/ 应用程序上安装了 Passport,使其能提供 OAuth 服务。然后他再创建一个 http://consumer.dev/ 应用程序作为客户端,下文中我们称其为 consumer
下面是他展示的管理界面(使用了上文提到的 vue 的三个组件)
file
下面是创建 client 的界面
file
当你创建完 client 后,你会获得一个 client ID,现在将此 ID 放到上文提到的 consumer 应用程序中,写入到其配置文件里。
下面是 Taylor 展示的 consumer 应用程序路由:
// routes/web.php

use Illuminate\Http\Request;

// First route that user visits on consumer app
Route::get('/', function () {
    // Build the query parameter string to pass auth information to our request
    $query = http_build_query([
        'client_id' => 1,
        'redirect_uri' => 'http://consumer.dev/callback',
        'response_type' => 'code',
        'scope' => 'conference'
    ]);

    // Redirect the user to the OAuth authorization page
    return redirect('http://passport.dev/oauth/authorize?' . $query);
});

// Route that user is forwarded back to after approving on server
Route::get('callback', function (Request $request) {
    $http = new GuzzleHttp\Client;

    $response = $http->post('http://passport.dev/oauth/token', [
        'form_params' => [
            'grant_type' => 'authorization_code',
            'client_id' => 1, // from admin panel above
            'client_secret' => 'abc', // from admin panel above
            'redirect_uri' => 'http://consumer.dev/callback`,
            'code' => $request->code // Get code from the 
        ]
    ]);

    return json_decode((string) $response->getBody(), true)['access_token'];
});
当你使用配置好的 client ID 等数据访问 http://consumer.dev/ 时,它会自动重定向到 http://passport.dev/ 里。
file
当你认证成功后,Passport 将重定向回你的 callback URL,在上文的例子中,它将重定向回 http://consumer.dev/callback,现在你将获得一个 token,通过这个 token 你能获取到用户的相关权限。

测试你的 token

在轻松的做完这一切后,Taylor 在他的 Passport 应用程序中创建了一个路由文件 routes/api.php,我们看一下如何使用其便捷的测试你的 API。
首先,在 Passport 应用程序路由中添加以下代码:
// routes/api.php
Route::get('/user', function (Request $request) {
    return $request->user();
});
由于在 routes/api.php 中的所有路由会自动加载 API 中间件,所以它会自动条用 auth:api 来验证用户。
接下来,打开你常用的 REST 客户端(如 Postman,Paw 又或者是你自己手写 PHP 代码请求接口)请求接口 http://passport.dev/api/user,当然你首先需要确认你的请求中 header 的 Content-Type 和接收信息中 header 的 Accept 都为 application/json
如果验证不通过,你会收到 401 回应:
{
  "error": "Unauthenticated."
}
现在,你想起来 access token 没?复制这个 token,然后将其加入到你请求 header 的 Authorization 中,设置它的值为 Bearer: TOKENHERE,TOKENHERE 就是你刚才获取复制的 token 了。现在,你应该能看到正常的返回值了:
{
  "id": 1,
  "name": "Matt Stauffer",
  "email": "matt@mattstauffer.co",
  "created_at": "2016-07-30 10:45:00",
  "updated_at": "2016-07-30 10:45:00"
}
就这样,你就快速的配置好你的 OAuth 2 API 了。
Passport 还有其他的功能,我们一起来看一下。

管理客户端 token 界面

file
请记住,这只是一个示范界面,你不一定使用 vue 来构建这个界面。
Passport 提供了非常有用的工具来创建测试 token,你不需要再创建一个完整的 consumer 应用程序来测试你的 API,你可以创建 personal tokens 来进行测试:
php artisan make passport:client --personal
现在你可以去 Personal Access Tokens 界面点击 “Create New Token” 按钮,它将生成新的 token。你可以删除这个 token,就像你可以撤销你的 client tokens 一样。

Scope 中间件

使用 scope 可以定义你的应用程序中的每个请求可以使用何种中间件。每个 scope 都有名称和描述,这样方便在程序中调用。
我们现在来看一下如何简单高效的定义 scope 中间件。
现在你的应用程序中有两个中间件,你可以给他们添加别名方便你快速调用,在这里我们分别起名为 anyScope 和 allScopes
现在修改一下 app/Http/Kernel.php 文件:
// App\Http\Kernel
...
protected $routeMiddleware = [
    ...
    // you can name these whatever you want
    'anyScope' => \Laravel\Passport\Http\Middleware\CheckForAnyScope::class,
    'allScopes' => \Laravel\Passport\Http\Middleware\CheckScopes::class,
];
现在,在每个路由后面你都可以调用这两个中间件进行访问权限控制,如果你使用 anyScope,则当用户拥有任一指定的 scope 即可访问该路由。如果你使用 allScopes,则用户必须拥有所有指定的 scope 才可以访问该路由。
在下面的例子中,程序将限制用户的访问权限,除非他们有 conference scope。
Route::get('/whatever', function () {
    // do stuff
})->middleware('anyScope:conference');

// Any of the given scopes
Route::get('/whatever', function () {
    // do stuff
})->middleware('anyScope:conference,otherScope');

// All of the given scopes
Route::get('/whatever', function () {
    // do stuff
})->middleware('allScopes:conference,otherScope');

结语

我编写过很多的 OAuth 服务,这过程非常痛苦。Passport 是我非常喜欢的新功能,不仅仅是因为它简化了我之前非常痛恨的集成,它还提供了很多我之前没想到的新功能,我现在很迫不及待的想使用它。
全文完

链接


reference : https://phphub.org/topics/2675

沒有留言:

wibiya widget