8. Laravel5学习笔记:在laravel5中使用OAuth授权

OAuth2.0简介

关于它的介绍,给出以下两篇文章,相信看完,应该对它有一定程度的了解:
[1] 理解OAuth 2.0 —— 阮一峰
[2] 帮你深入理解OAuth2.0协议 —— seccloud

这里我主要阐述的是在laravel5中使用OAuth2.0。关于这个协议本身,以及运行流程希望大家看完以上两篇文章,理解后,再看我后面的内容!

Laravel5中安装OAuth2.0

OAuth2.0在官方中提供了 php的库 ,但是我们这里并不直接使用它官方提供的 Server Libraries ,我们使用github上 oauth2-server-laravel 这个库,它是经过改造,适合 Laravel5 的(Laravel4的安装就选对版本)。

使用教程

其实关于如何使用这个包,在 oauth2-server-laravel 提供的项目已经说得很清楚了,但是文档首先是英文的不便于只管理解,然后有几个小坑,这里用中文转述及补全一下:

安装

首先要用它,就需要先安好它。由于目前Laravel5的稳定版还没有发布,只提供了开发版(这里按照github上的文档安装会出错就是由于提供的版本还没有发布,需要使用开发版),所有安装如下:

"lucadegasperi/oauth2-server-laravel": "~4.1@dev",
"illuminate/html": "~5.0"

ps:这里安装 illuminate/html 是由于从Laravel5开始这个包就被移除了,然后我们项目中需要使用它,但是它并不是必须的,你可以选择不安装,不安装你在页面中将不能使用 {!! Form::hidden('client_id', $params['client_id']) !!} 这种操作。

配置

配置完全可以按照提供的文档来,步骤如下:

  • config/app.phpproviders 数组增加服务提供者
LucaDegasperi\OAuth2Server\Storage\FluentStorageServiceProvider::class, LucaDegasperi\OAuth2Server\OAuth2ServerServiceProvider::class, // viewForm表单使用,与OAuth无直接关系,只是为了布局方便 Illuminate\Html\HtmlServiceProvider::class,
  • config/app.phpaliases 数组增加Facades
'Authorizer'=> LucaDegasperi\OAuth2Server\Facades\Authorizer::class, // 与OAuth2.0认证无直接关系,只是为了方便布局使用 'Form' => Illuminate\Html\FormFacade::class, 'HTML' => Illuminate\Html\HtmlFacade::class,
  • 修改app/Http/Kernel.php,配置相关的中间件
    protected $middleware = [
        // 注释掉
        //\App\Http\Middleware\VerifyCsrfToken::class,
        \LucaDegasperi\OAuth2Server\Middleware\OAuthExceptionHandlerMiddleware::class, ]; protected $routeMiddleware = [ // 增加以下路由,原先的保留 'oauth' => \LucaDegasperi\OAuth2Server\Middleware\OAuthMiddleware::class, 'oauth-owner' => \LucaDegasperi\OAuth2Server\Middleware\OAuthOwnerMiddleware::class, 'check-authorization-params' => \LucaDegasperi\OAuth2Server\Middleware\CheckAuthCodeRequestMiddleware::class, 'csrf' => \App\Http\Middleware\VerifyCsrfToken::class, ];
  • 执行 php artisan vendor:publish 生成相关的配置文件,你在 config 会看到生成了一个 oauth2.php 文件。

  • 在数据库中生成OAuth2.0需要的数据库表,只需要执行 php artisan migrate 即可,你会在数据库中看到以下表的生成:

  • 选择客户端的授权模式,OAuth2.0有四种模式,分别是:Authorisation code grantImplicit grantResource owner credentials grantClient credentials grant。这里我就介绍微博使用的 Authorisation code grant 该模式,相信大家一通百通。
    选择后,首选要在 config/oauth2.php 中配置 grant_types 选项:

'grant_types' => [
    'authorization_code' => [
        'class' => '\League\OAuth2\Server\Grant\AuthCodeGrant',
        'access_token_ttl' => 3600,
        'auth_token_ttl' => 3660
    ]
]

代码与数据库的处理

数据库初始化数据

在写代码之前,我们先来把数据库里边填入一些初始数据。
首先是增加一个用户,推荐大家使用 Laravel5 自带的 Seeder 来完成。我就不说过程了,直接告诉大家该初始化一些什么数据!
* 向 users table添加一个用户
* 向 oauth_clients table 添加一个client,需要注意的是它的id是字符串类型,相当于申请微博时分配的AppKey
* 向 oauth_scopes table添加两天记录,如下图:
这里写图片描述
* 向 oauth_client_scopes table中添加记录如下:

* 向 oauth_client_endpoints 添加记录如图:
这里写图片描述
ps:此处应该注意,redirect_uri 的值应该是填写你自己本地能够回调的地址,不要一味模仿,请根据自己的实际情况

至于添加这些数据到底是神马意思,相信根据表的命名可以猜出一二,是在不清楚的可以留言询问哈。

终于到了代码阶段

这里为了简便,我将所有代码按照github上提供的文档,卸载了路由文件中,建议项目中使用时,请将闭包中的代码移植到控制器中,否则你将无法使用laravel提供的路由缓存功能。
整个路由代码如下:

// 这是需要经过OAuth2.0授权后才能访问的资源,不信你直接访问绝对会报错
Route::get('/', ['middleware' => ['oauth'], function () {
    return view('welcome');
}]);
// 登陆
Route::get('auth/login', function() {
    return view('auth.login');
});
Route::post('auth/login', function() {
    if(Auth::attempt(Input::only('email', 'password'))){
        return Redirect::intended('oauth');
    }
});
// 这会让页面跳转到一个授权页面,提供给用户进行操作
Route::get('oauth/authorize', ['as' => 'oauth.authorize.get', 'middleware' => ['check-authorization-params', 'auth'], function(){
    // display a form where the user can authorize the client to access it's data
    $authParams = Authorizer::getAuthCodeRequestParams();
    $formParams = array_except($authParams,'client');
    $formParams['client_id'] = $authParams['client']->getId();
    return View::make('oauth.authorization-form', ['params'=>$formParams,'client'=>$authParams['client']]);
}]);
// 用户通过授权,客户端向认证服务器申请令牌的HTTP请求
Route::post('oauth/authorize', ['as' => 'oauth.authorize.post','middleware' => ['csrf', 'check-authorization-params', 'auth'], function() {

    $params = Authorizer::getAuthCodeRequestParams();
    $params['user_id'] = Auth::user()->id;

    $redirectUri = '';

    // if the user has allowed the client to access its data, redirect back to the client with an auth code
    if (Input::get('approve') !== null) {
        $redirectUri = Authorizer::issueAuthCode('user', $params['user_id'], $params);
    }

    // if the user has denied the client to access its data, redirect back to the client with an error message
    if (Input::get('deny') !== null) {
        $redirectUri = Authorizer::authCodeRequestDeniedRedirectUri();
    }

    return Redirect::to($redirectUri);
}]);
// 认证服务器发送的HTTP回复
Route::post('oauth/access_token', ['as' => 'access_token', function() {
    header('Content-Type:application/json; charset=utf-8');
    return Response::json(Authorizer::issueAccessToken());
}]);
// 用来客户端向认证服务器申请令牌的HTTP请求的页面,便于发送post请求
Route::get('/callback', function(){
    if(Input::has('code')){
        return view('callback');
    }
});

以上使用到的视图文件,请参考Laravle-OAuth2项目。

效果展示

这里页面效果的演示,我会按照OAuth2.0的执行过程来进行说明,先将 授权码模式 的执行流程帖在这里:
8. Laravel5学习笔记:在laravel5中使用OAuth授权_第1张图片
中文解释如下:

(A)用户访问客户端,后者将前者导向认证服务器。
(B)用户选择是否给予客户端授权。
(C)假设用户给予授权,认证服务器将用户导向客户端事先指定的”重定向URI”(redirection URI),同时附上一个授权码。
(D)客户端收到授权码,附上早先的”重定向URI”,向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。
(E)认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。

对应A步骤:
这里写图片描述
A步骤中,客户端申请认证的URI,包含以下参数:
redirect_uri:表示重定向URI,可选项
state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。
response_type:表示授权类型,必选项,此处的值固定为”code”
client_id:表示客户端的ID,必选项
scope:表示申请的权限范围,可选项

对应B步骤:
通过A步骤访问后,显示的页面就是把是否授权展现给了用户,用户可以进行选择,假设用户选择 Approve ,那么继续

对应C步骤:
8. Laravel5学习笔记:在laravel5中使用OAuth授权_第2张图片
这时候观察地址栏发现地址栏中显示的地址是我们的回调地址,以及携带了code及state的参数。观察控制台也会发现302的状态码。

对应D步骤:
本身来说这一步是不可见的,对于用户,但是为了演示,所以提供了这样一个post表单,正常项目中大家可以通过客户端后台向AS发送认证的post请求,此时AS会返回一个json数据,从中取出 access_token 后,附加在相关的资源URI后面,即可访问该资源了。

对应E步骤:
获取服务器返回数据

{
    "access_token":"Zv0anjwEjAm7SFZGjH1K3MRW6yNj56SuC5MGI9kB",
    "token_type":"Bearer",
    "expires_in":3600 }

OK,现在可以测试访问需要授权的资源了。针对于我们这里就是:

http://localhost/llaravel/public/ ,此时如果不添加参数,直接访问会看到以下报错信息:

{
    "error":"invalid_request",
    "error_description":"The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Check the \"access token\" parameter." }

正确的访问姿势是:http://localhost/llaravel/public?access_token=Zv0anjwEjAm7SFZGjH1K3MRW6yNj56SuC5MGI9kB,此时访问,你就会看到Laravel5漂亮的首页界面了。

OK,到这里就讲完了!希望对你有帮助。

Laravel5专题目录

你可能感兴趣的:(OAuth,oauth2-0,Laravel授权,oauth+L5,oauth协议的使用)