laravel passport oauth 使用心得

使用场景:

例如:

  • 某个网站,某用户未注册,注册时提示可微信账号登录(github, google都有类似
  • 当然也可以直接用作API的验证

API登录验证场景(passport个人授权码):

提示:现在基本都是前后端分离了,所以前端要调用后台的接口,就有个验证的过程,一般情况都是用户登录后,后台返回一个token,然后前端在每次请求后台接口的时候都通过请求头将该token传给后台,后台进行验证。这种情况不一定要用passport,用jwt或者直接在数据库中加一个字段也行。

步骤:

  • 创建一个laravel项目
composer create-project --prefer-dist laravel/laravel blog "8.5.*"
  • 安装passport
composer require laravel/passport
  • 我的mysql是5.6版本,所以在执行数据迁移之前先修改一下代码,不然会报错。在
    App\Providers\AppServiceProvider
use Illuminate\Support\Facades\Schema;
    public function boot()
    {
        //
        Schema::defaultStringLength(191);
    }
  • 执行数据迁移,自己提前在.env文件配置好数据库
php artisan migrate
  • 修改User模型,Models/User.php,这个看你自己项目的用户表在哪里,该trait提供一些常用方法
use Laravel\Passport\HasApiTokens;
use HasApiTokens,HasFactory, Notifiable;
  • 修改conffig/auth.php,修改API的认证方式,将api的driver改为passport
'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'passport',
            'provider' => 'users',
            'hash' => false,
        ],
    ],
  • 生成安全访问令牌的加密秘钥。另外,该命令也将创建用于生成访问令牌的 “个人访问” 客户端和 “密码授权” 客户端 ,命令执行完后,会在oauth_clients表中新增两条数据和在项目storage目录下生成两文件,oauth-private.key,oauth-public.key
php artisan passport:install

###命令执行完,oauth_clients表中的两条数据,一条name=Laravel Personal Access Client的数据是"个人访问"客户端需要用到的,也就是我们现在的API这种模式,还要一条是name=Laravel Password Grant Client的数据是“密码授权” 客户端用到。这个“密码授权”简单的就是说,需要用户的账户密码,还有该条数据的id,secret等参数去请求passport自带的路由(http://passport-server/oauth/token),认证成功就会返回token
  • 创建两个控制器来测试,并增加路由,一个是Login,一个User,Login不需要验证token,User需要验证token
//api.php路由文件,一个是有中间件,一个没有,中间件就是验证token的

Route::post('login',[\App\Http\Controllers\LoginController::class,'login']);
Route::get('user',[\App\Http\Controllers\UserController::class,'index'])->middleware('auth:api');
  • LoginController的Login方法,我没有写具体的验证,我只是写怎么生成token
   //
    function login(Request $request){

        //验证合法性等等。。。。

        //登录成功,生成token
        $user = User::where("name",'yang')->first();
        $token = $user->createToken('personal token');
        return $token;
    }

  • UserController用来获取用户信息,必须是登录成功才能获取,所以需要传递token
//LoginController中的index方法,user方法中的api参数就是在config/auth.php中的guards中的值,
//因为api guard不是默认的,所以需要显式的指定要用guard

function index(Request $request){
    return $request->user('api');
}
  •  返回结果,请求一定要在header头中带上token,格式是Authorization:Bearer Token。。。Bearer后面有一个空格

第三方登录(passport的授权码模式):

提示:大致流程是,

      客户端==我自己某个网站

      认证服务器==微信服务器

      我的网站想接入微信的第三方登录,这样用户就不用在重新注册一个账号了,可以直接用微信用户的信息,但是微信不能平白无故给我们网站这些信息呀,所以就有了这种模式

  1. 用户访问客户端,客户端导向至认证服务器
  2. 用户如果没有在认证服务器上登录,那跳转到登录页面,然用户先登录认证服务器
  3. 登录成功后跳转到授权页面,也就是用户选择是否授权的页面
  4. 用户给予授权后,认证服务器会跳转到事先指定的客户端的某个地址,地址上并会附上一个code,该code是一次性的,并且时效很短
  5. 客户端收到该code后,会向认证服务器申请令牌,该过程是由客户端后台服务器上完成,用户不可见
  6. 认证服务器效验了code后,会返回access_token和refresh_token

具体实现(上面的配置依然有效,也就是上面API模式的步骤,下面也要配置):

  • 先生成auth的前端内容
composer require laravel/ui --dev
  • 在执行
php artisan ui vue --auth
  • 这个时候访问登录等页面发现没有样式,在执行
npm install
npm run dev
  • 再生成一个客户端,也就是在oauth_clients表中再加一条数据,该数据和之前那2条作用是不一样的,该命令执行后,会提示你输入名称和回调地址,也就是用户点击了允许授权后,认证服务器会跳转回该地址,并带有code
php artisan passport:client
  • 在App\Providers\AuthServiceProvider的boot方法中注册passport默认自带的路由
use Laravel\Passport\Passport;
Passport::routes();
//注册有哪些scope,相当于设置权限,不设置就表示全部,这些scope需要在定义路由的时候指定好
        /*Passport::tokensCan([
            'view-posts' => 'Views',
            'view-user' => 'View user',
        ]);*/

Passport::tokensExpireIn(now()->addHour(2)); // access_token 过期时间
Passport::refreshTokensExpireIn(now()->addDays(3)); // refresh_token 过期时间
Passport::personalAccessTokensExpireIn(now()->addSeconds(20));//个人访问令牌过期时间
  • 直接访问认证服务器的oauth/authorize路由,这是passport自带的,参数换成刚刚生成那条客户端数据中的参数,就是oauth_clients表的数据
http://www.passportapi.com/oauth/authorize?client_id=3&redirect_uri=http://localhost/callback&response_type=code&scope=*

  •  用户授权后,将会跳转回http://localhost/callback?code=xxxxxx,并会带有code码,客户端获取到这个码以后就去请求access_token和refre_token

  •  获取到code后,那code和其他参数换取access_token,请求oauth/token路由 

  • 拿到token后客户端就可以用这个access_token去请求认证服务器上的接口了,这个token还是需要放在header请求头中 
  • 还有很多passport自带的路由,可以去官方文档看看(到这里其实可以告一段落了,后面只是补充
  • 多提一嘴,授权码模式还能指定更加细化的权限,细致到每个路由,用scope来指定
  • 默认作用域
//如果客户端没有请求任何特定的范围,你可以在 App\Providers\AuthServiceProvider 类的 boot 方法中使用 Passport::setDefaultScope 方法来定义默认的作用域。

use Laravel\Passport\Passport;
//这里相当于指定所有的范围,place-order是scope的名,接口中scope参数需要的就是这个,Place orders只是描述,方便看而已
Passport::tokensCan([
    'place-orders' => 'Place orders',
    'check-status' => 'Check order status',
]);
//这里是如果客户端没有指定范围,那我们可以给个默认的范围,*代表全部
Passport::setDefaultScope([
    'check-status',
    'place-orders',
]);
  • 带有作用域的请求:place-orders
http://www.passportapi.com/oauth/authorize?client_id=3&redirect_uri=http://localhost/callback&response_type=code&scope=place-orders
  • 个人访问令牌也可以指定作用域

//LoginController 
$token = $user->createToken('My Token', ['place-orders'])->accessToken;
  • 有了作用域,应该怎么验证呢?先在认证服务器中加中间件
//Passport 包含两个中间件,可用于验证传入的请求是否包含访问指定作用域的令牌。 使用之前,需要将下面的中间件添加到 app/Http/Kernel.php 文件的 $routeMiddleware 属性中:

//scopes 中间件的可以简单理解成and,意思就是说在定义的路由的时候,要同时拥有指定的作用域才有权限
//scope 中间件可以简单理解成or,  意思就是说在定义的路由的时候,只要拥有一个指定的作用域就有权限

'scopes' => \Laravel\Passport\Http\Middleware\CheckScopes::class,
'scope' => \Laravel\Passport\Http\Middleware\CheckForAnyScope::class,
  • 路由可以使用 scopes 中间件来检查当前请求是否拥有指定的 所有 作用域:
Route::get('/orders', function () {
    // 访问令牌具有 "check-status" 和 "place-orders" 作用域...
    //scopes 中间件的可以简单理解成and,scopes:check-status,place-orders意思就是说在定义的路由的时候,要同时拥有check-status和place-orders作用域才有权限
    //scope 中间件可以简单理解成or,  scope:check-status,place-orders意思就是说在定义的路由的时候,只要拥有check-status或者place-orders作用域就有权限
})->middleware(['auth:api', 'scopes:check-status,place-orders']);

补充事项:

提示:补充点

想起哪条再补充:

  • 访问令牌的过期时间问题,oauth_access_tokens表是存放access_token的,里面有个过期时间字段expire_at,该字段只是记录该access_token的过期时间,我们有时候就想手动改这个时间,让access_token过期,这是不行的,因为过期时间在生成的时候就已经加密在返回的access_token里面了,生成后就不受数据表控制了,如果非要让该access_token失效就将revoked字段改为1
  • passport oauth 有4种模式。这只是其中2种,后续再补充吧。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值