您的当前位置:首页正文

手摸手,教你使用 laravel-passport 实现 oau

来源:图艺博知识网

知识点概括

环境介绍

  1. 使用 laradock 作为 laravel 的开发环境

PHP 7.2、MySQL 5.7

  1. Node 环境

node 9.8、npm 5.6

项目架构

  1. Server 项目用于搭建 验证授权服务器
  2. Client 项目用于 第三方应用
Oauth 2.0 验证流程示意图(引用于:阮一峰博客)

设计逻辑

实现类似与微信授权登陆的逻辑。
挡在微信中进入其它网页时,会出现类似授权的页面,当点击授权后即可获取用户的信息。


image.png

Server 项目搭建

  1. 首先使用命令创建 Server 项目
composer create-project laravel/laravel --prefer-dist server
  1. 配置数据库
# .env
...
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=server
DB_USERNAME=root
DB_PASSWORD=root
...

laradock 中 host 必须填写 mysql,自动转发到 mysql 容器中

  1. 安装laravel/passport
composer require laravel/passport

laravel 5.5 以后有自动发现机制,不需要配置 provider,低于该版本请按照手册自行配置。

  1. 执行数据库迁移,并添加 auth 脚手架。
$ php artisan migrate
$ php artisan make:auth

当执行完 make:auth 后首页上就会出现注册与登录。

image.png
  1. 生成 passport key 以及一些 password keys
php artisan passport:install
image.png
  1. 配置 config 文件
    将 api 的driver 更换为 passport
# config/auth.config
...
'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'passport',
            'provider' => 'users',
        ],
    ],
...

这一步是实现 API Auth 授权中间件默认使用的驱动

  1. User 使用 Password 提供的 Trait
# App\User
use Laravel\Passport\HasApiTokens;

class User extends Authenticatable
{
  use HasApiTokens;
  ...
}
  1. 配置 Passport 相关路由信息
# App\Providers\AuthServiceProvider
...
use Laravel\Passport\Passport;

class AuthServiceProvider extends ServiceProvider
{
     ...
    public function boot()
    {
        $this->registerPolicies();

        // Passport 路由
        Passport::routes();
        // Passport Token 过期时间
        Passport::tokensExpireIn(Carbon::now()->addDay(15));
        // Passport Refresh Token 过期时间
        Passport::refreshTokensExpireIn(Carbon::now()->addDay(30));
    }
}
  1. 生成前端脚手架,默认提供了 vue 相关模板,需要使用到 node
php artisan vendor:publish  --tag=passport-components
image.png
  1. 使用 npm 或 cnpm 命令安装 package.json 的相关依赖
    composer.json 与 package.json 类似,npm 与 composer 类似。使用 npm 必须安装 node 环境。npm 与 composer 类似,境外资源拉取非常慢,所以推荐使用淘宝镜像。具体设置方法请 Google。
npm install 
image.png
  1. 然后将 component 组件注册到 vue 的根实例中
# resources/assets/js/app.js

    'passport-clients',
    require('./components/passport/Clients.vue')
);


    'passport-authorized-clients',
    require('./components/passport/AuthorizedClients.vue')
);


    'passport-personal-access-tokens',
    require('./components/passport/PersonalAccessTokens.vue')
);
image.png
  1. 编译文件,生成 app.js 和 app.css
npm run dev
image.png

有一些同学可能会存在相关问题,比如笔者就遇到一个bug。Module build failed: ReferenceError: Unknown plugin "transform-runtime",当遇到这个bug时第一时间google了一下,然后各种无法解决,仔细一看,原来是项目的上一级目录中存在一个 .babelrc文件,该文件 上一个 vue 项目的残余(没删除干净),然后删除之后就可以了。
这里笔者要说明的是:遇到问题不要紧张,首先看一下报错的信息,如果是 依赖没安装成功就删除 node_modules,重新安装下。如果是存在其它 bug,首先看看是不是本项目的,如果不是就删除它,如果是的话那么就 google 一下,查找一下解决方式,或者你可以留言。

  1. 这时,你就需要可以在 blade 模板里面引入编译好的 css 和 js 就可以了。
# resources/view/passport.blade.php
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="{{ mix('css/app.css') }}">
</head>
<body>
    <!-- Vue 默认绑定的根节点 -->
    <div id="app" class="container">
        <passport-clients></passport-clients>
        <passport-authorized-clients></passport-authorized-clients>
        <passport-personal-access-tokens></passport-personal-access-tokens>
    </div>

    <!-- 必须放在 根节点 之后,否则无法正常解析-->
    <script src="{{ mix('js/app.js') }}"></script>
</body>
</html>
  1. 添加路由
# routes/web.php
Route::get('/passport', function () {
    return view('passport');
});
  1. 访问路由
server.test/passport
image.png

页面渲染,但是报错了 401 错误,这说明必须登录之后才能访问该路由。那么进入首页登录一下即可,没有账号就注册一个。


image.png
  1. 成功,并且无报错信息


    image.png
  2. 创建一个 Client


    image.png
image.png
  1. 使用 浏览器 测试一下
http://server.test/oauth/authorize?client_id=your_client_id&redirect_uri=your_redirect_uri&response_type=code&scope=*

将 client_id 和 redirect_uri 替换成你自己的即可

image.png
  1. 响应数据
http://client.test/authorizations?code=def50200b4bd56c76cf885df8f4871b1325aa23571c07fe149086c4a3795c7b6e286d19aef3101330fcaa7e19a8bebaabf4a3cb4cdfa6208934a4d42db4e5f2eee1ef0a78ae6da976da9764c75d7561f43cd12d3a2aacc20b94cc12b71aa2b7464c44438524e8b73c256b655168ed6087da8a82c011c1f86deb3a72cf30a4eba955579efce5cf007993c13ad1783beb43bb30980f5ac54b0a559148df3182839ee6522c0175eb24ce917f36a2b1bb70b4278dc29640d8251a83a9e8a58c559b8b7304e2edfaeb24c9f248f1eb0187ecff76ecb8ebdbd57a1da91ce4c84142946065cbdb5187e4f92f012ce49497f6fd471c2a9a6538f89a8194dda8b976f42377fa1b429237b7bf2606ab64fe459532fba35f61fb8262efc8b4931edcaaf0ff6ec87dba9894916a90ada15c9fd8f44a7520996e44bfa38fd8ae2c719cb098e673887eddbb2a01b5af9f7c062ffb991536cbdeff275a3b7a2556c595998eec98dda063759aa3d
  1. 通过 code 获取 access_token


    image.png

把 client_id 和 client_secret 更换为你自己的

  1. 响应数据解读
    token_type: Bearer 是 Oauth 2.0 的一种认证模式,一般均为此。
    expires_in: 过期时间
    access_token: 通讯密钥
    refersh_token:刷新Token,是在 access_token 过期后,可以用此更换新的 access_token

还记得我们在 AuthProvider中设置的过期时间么?token 过期时间比 refresh_token 过期时间要短,我们设置的是 15天 和 30 天。

  1. 这时就可以拿着 access_token 去读取用户信息了
    首先,定义一个 API 路由
# routes/api.php

Route::middleware('auth:api')->get('/user', function (Request $request) {
    $user = \Auth::guard('api')->user();
    return response()->json($user);
});

比如,在 API 路由中去读取用户信息,使用 Postman 测试一下。


image.png image.png
  1. 恭喜,基本完成了。
    当然,笔者做的实验是利用 client 去实现 postman 的功能,但是发现 postman 更好用。client 端的代码其实就是做了一层转发的功能,让服务器保存 client_secret 更加安全。但基于实验,你完全可以使用 postman。

这里笔者只是基本完成了 laravel-passport 的授权模式, 如果还要更深的研究,你可以留言,我可以进行更加具体的教程解读。

Client 端代码
Top