1. 概述
API 通常使用令牌(token)进行认证并且在请求之间不维护会话(Session)状态。Laravel 官方扩展包 Laravel Passport 让 API 认证变得轻而易举,Passport 基于 Alex Bilbie 维护的 League OAuth2 server,可以在数分钟内为 Laravel 应用提供完整的 OAuth2 服务器实现。本文主要讲述Oauth2 的'grant_type' => 'password'
密码授权来做Auth验证
2. 单表用户登录
2.1 安装
首先通过 Composer 包管理器安装 Passport:
根据laravel不同的版本,加载不同的管理包,如果你使用laravel5.4版本;使用命令composer require laravel/passport v4.*
;不然可能因为版本问题,加载失败
composer require laravel/passport
成功安装Passport包之后,我们需要设置他们的服务提供者。所以,打开你的config / app.php文件,并在其中添加以下提供程序。
'providers' => [ .... Laravel\Passport\PassportServiceProvider::class, ],
2.2 迁移数据库
Passport 服务提供者为框架注册了自己的数据库迁移目录,所以在注册服务提供者之后(Laravel 5.5之后会自动注册服务提供者)需要迁移数据库,Passport 迁移将会为应用生成用于存放客户端和访问令牌的数据表:
php artisan
2.3 生成加密键oauth_clients
php artisan
该命令将会创建生成安全访问令牌(token)所需的加密键,此外,该命令还会创建“personal access”和“password grant”客户端用于生成访问令牌,生成记录存放在数据表 oauth_clients
2.4 修改user模型
添加 Laravel\Passport\HasApiTokens trait 到 App\User 模型,该 trait 将会为模型类提供一些辅助函数用于检查认证用户的 token 和 scope
<?php namespace App; use Laravel\Passport\HasApiTokens; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use HasApiTokens, Notifiable; }
2.4.1 重置验证字段
先看passport封装源码,然后根据自己需求更改我们的配置;追踪源码如下
<?php namespace Laravel\Passport\Bridge; use RuntimeException; use Illuminate\Contracts\Hashing\Hasher; use League\OAuth2\Server\Entities\ClientEntityInterface; use League\OAuth2\Server\Repositories\UserRepositoryInterface; class UserRepository implements UserRepositoryInterface {
(1)重置验证username字段,如果密码不需要重置,则不用管一下代码;
由源码method_exists($model, 'findForPassport')
我们如果要重置,只需要在User模型中添加findForPassport
方法即可
默认验证email字段,如果你想验证phone
和email
一起验证;在User表中添加如下方法:
public function findForPassport($username) { return $this->orWhere('email', $username)->orWhere('phone', $username)->first(); }
(2)重置验证password字段,如果密码不需要重置,则不用管一下代码;
由上面源码method_exists($user, 'validateForPassportPasswordGrant')
我们可以知道,只需要在我们的User模型中添加validateForPassportPasswordGrant
方法就好了;代码如下
public function validateForPassportPasswordGrant($password) {
2.5 注册获取Token路由
接下来,需要在 AuthServiceProvider 的 boot 方法中调用 Passport::routes 、enableImplicitGrant、tokensCan、tokensExpireIn、refreshTokensExpireIn具体作用看注释
<?php
namespace App\Providers;
use Laravel\Passport\Passport;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider { /** * The policy mappings for the application. * * @var array */ protected $policies = [ 'App\Model' => 'App\Policies\ModelPolicy', ]; /** * Register any authentication / authorization services. * * @return void */ public function boot() { $this->registerPolicies(); Passport::routes();
2.6 修改项目auth配置文件
文件位置:congig/auth.php
接口使用api, 保护项( driver )改为 passport 。此调整会让你的应用程序在接收到 API 的授权请求时使用 Passport 的 TokenGuard 来处理:
return [ ..... 'guards' => [ ... 'api' => [ 'driver' => 'passport', 'provider' => '
2.7 配置完成,测试使用
个人为了方便使用,封装一个工具类来进行token测试;个人放在App\Helpers
文件夹下;代码如下:
<?php namespace App\Helpers; use GuzzleHttp\Client; use GuzzleHttp\Exception\RequestException; trait ProxyTrait {
创建路由(router/api.php
) 验证为:auth中间件,guards为api
Route::post('login', 'API\UserController@login'); Route::post('register', 'API\UserController@register'); Route::group(['middleware' => 'auth:api'], function(){ Route::post('details', 'API\UserController@details'); });
编辑控制器
- 利用passport自带方法,实现token请求
- 利用封装工具来实现获取token
注意
获取下一个token,记得删除上一个token值(如果不删除之前的token也可以验证成功)
<?php namespace App\Http\Controllers\API; use App\Helpers\ProxyTrait; use Illuminate\Http\Request; use App\Http\Controllers\Controller; use App\User; use Illuminate\Support\Facades\Auth; use Validator; class UserController extends Controller { use ProxyTrait; public $successStatus = 200;
3. 多表用户登录
现在大部分公司用到前后端分离技术,可能存在APP,Web,小程序共存的情况,就会出现多表处理Token值;已微信小程序登录为例:
3.1 修改项目auth配置文件(UserCus表为用户表)
文件位置:congig/auth.php
接口使用xcx, 保护项( driver )改为 passport 。此调整会让你的应用程序在接收到 API 的授权请求时使用 Passport 的 TokenGuard 来处理:
<?php
return [ 'defaults' => [ 'guard' => 'web', 'passwords' => 'users', ], 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport', 'provider' => 'users', ], 'xcx' => [ 'driver' => 'passport', 'provider' => 'usercu', ] ], 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\User::class, ], 'usercu' => [ 'driver' => 'database', 'model' => 'App\Models\UserCu::class', ], ], 'passwords' => [ 'users' => [ 'provider' => 'users', 'table' => 'password_resets', 'expire' => 60, ], 'usercu' => [ 'provider' => 'usercu', 'table' => 'password_resets', 'expire' => 60, ], ], ];
3.2 创建用户模型
1.根据自己需求设置username , 系统默认为email
2.根据自己需求设置password验证,系统默认为Hash算法
3.新建表如果报错没有创建关联关系,请创建
<?php namespace App\Models; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; use Laravel\Passport\HasApiTokens; class Usercu extends Model { use HasApiTokens,Notifiable;
3.3 创建中间件,设置config文件
由2.4.1源码我们可以看到$provider = config('auth.guards.api.provider');
系统只默认了api
这一种情况,可是我想验证xcx
;代码如下:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\Config; class PassportMiddleware {
3.4 给获取token路由加上中间件
更改步骤2.5文件中的代码,加一个中间件,根据实际需求去加;代码如下:
<?php namespace App\Providers; use Carbon\Carbon; use Laravel\Passport\RouteRegistrar; use Laravel\Passport\Passport; use Illuminate\Support\Facades\Gate; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; class AuthServiceProvider extends ServiceProvider {
3.5 重置校验规则
根据自己需求重置,本人是因为前后端分离,多端多字段共同存在一个路由api中,所有要重置
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Auth\AuthenticationException; use Illuminate\Auth\Middleware\Authenticate; use Laravel\Passport\Http\Middleware\CheckClientCredentials; class Custom {
注册中间件
文件位置App\Http\Kernel.php
protected $routeMiddleware = [ ··· 'Custom' => App\Http\Middleware\Custom, ··· ];
3.6 配置完成,测试使用
创建路由(router/api.php
) 验证为:中间件为3.5重置验证规则中间件
Route::post('login', 'API\UserController@login'); Route::post('register', 'API\UserController@register'); Route::post('wxlogin', 'API\UserController@wxlogin'); Route::group(['middleware' => 'Custom'], function(){ Route::post('details', 'API\UserController@details'); });
UserController新增wxlogin方法(下面方法为测试方法,根据自己实际需求写自己的方法)
<?php namespace App\Http\Controllers\API; use App\Helpers\ProxyTrait; use Illuminate\Http\Request; use App\Http\Controllers\Controller; use APP\Models\Usercu; use Illuminate\Support\Facades\Auth; class UserController extends Controller { use ProxyTrait;