百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

「 原创 」Laravel 5.8 API 开发实战(四)

bigegpt 2024-10-18 04:21 10 浏览

《Laravel 5.8 API 开发实战(二)》《Laravel 5.8 API 开发实战(三)》主要讲述了 Jwt-Auth 的基本实现及无感刷新 Token,本篇主要讲述 API 守护 Passport,密码授权令牌的实现。

安装 Passport

用 composer 安装 passport,运行 composer require laravel/passport

安装完成后,passport 服务提供器会自动使用框架注册自己的数据库迁移目录,只需要运行 php artisan migrate 即可。

当然了,如果不想使用 passport 的默认迁移,可以在 AppServiceProvider 的 register 方法中调用忽略迁移的方法 Passport::ignoreMigrations


生成密钥

运行 php artisan passport:install,该命令会生成安全访问令牌时所需要的加密密钥


更新模型

上述命令执行完成,生成密钥后,需要将 Trait 添加到 APP/User 模型中,提供一些需要的辅助函数。

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Passport\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
    
    /**
     * 通过用户名/手机号码找到对应的用户信息
     *
     * @param string $username
     * @return User
     */
    public function findForPassport($username) {
        return $this->orWhere('username', $username)->orWhere('email', $username)->orWhere('phone', $username)->first();
    }
}


服务提供器(Provider)

在 app/Providers 目录下,修改 AuthServiceProviders.php 中的 boot 方法,调用 Passport::routes 函数,这个函数会注册一些必须的路由(发出 / 撤销 访问令牌(客户端 / 个人)等)

<?php

namespace App\Providers;

use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Laravel\Passport\Passport;

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();
    }
}


授权看守器(Guard)

修改配置文件 config/auth.php 中 api 的授权看守器 gurads,将 driver 选项改为 passport。

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

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


token 有效期

Passport 颁发的访问令牌,默认是一年有效的,如果想自定义访问令牌的有效期,可使用 tokensExpireIn 及 refreshTokensExpireIn 方法去设置(app/Providers/AuthServiceProvider.php)

public function boot() {
    $this->registerPolicies();
    Passport::routes();
    Passport::tokensExpireIn(now()->addDays(10));
    Passport::refreshTokensExpireIn(now()->addDays(30));
}


部署 passport

运行:php artisan passport:keys (该命令会生成 Passport 生成访问令牌所需的密钥)




密码授权令牌

OAuth2 密码授权机制,可以非常方便自己的客户端通过手机号码(或邮箱)+ 密码的形式,进行授权,获取访问令牌,无需遍历整个OAuth2 整个授权流程。

密码授权客户端

如果此前安装 passport 时,执行过 php artisan passport:install 命令的,将无需执行下面的命令,因为该指令已经生产两条数据,即生成了对应的客户端,具体可以查看 oauth_client 数据表。

若是未执行上述命令,可执行:php artisan passport:client --password ,对应的输入想要的用户名即可。


请求令牌

客户端创建后,就可以通过电子邮件地址与密码向 /oauth/token 发 POST 请求了,需要注意的是,该路由已经通过 Passport::routes 注册过,无需另外手动注册,如果请求成功,则会返回如下所示的 JSON 对象,包含 token_type(类型),expires_in(过期时间),access_token 及 refresh_token

{
    "token_type": "Bearer",
    "expires_in": 1296000,
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjQxOTI0MWIyMTYyMDkwMGEzMjBhZjVjZWUxNjgzYzkwZTE2Y2NiOTcyMzE3MzU4NzRiNmNkNTgxNTZjNzY3YzhlNjJiMjNlNWJkYzdjZDM1In0.eyJhdWQiOiI0IiwianRpIjoiNDE5MjQxYjIxNjIwOTAwYTMyMGFmNWNlZTE2ODNjOTBlMTZjY2I5NzIzMTczNTg3NGI2Y2Q1ODE1NmM3NjdjOGU2MmIyM2U1YmRjN2NkMzUiLCJpYXQiOjE1NTY1Mjk4NjUsIm5iZiI6MTU1NjUyOTg2NSwiZXhwIjoxNTU3ODI1ODY1LCJzdWIiOiIxIiwic2NvcGVzIjpbIioiXX0.ng5lmGdiwRGOxYRkW7R0Ox7VSb5pWIlRaxMbWikbIP0GyEhL4ABJjvA4LVNb8k0molnghbTrUxr8V9yNTI-dVzt8iNzEXEvQ2N_jBWL-96M85V_QybDq0nHMU5vdPqxbbcjZNoAz53GD-QQPpwlaT6X1IpjjkAcXKwY_SBywGG3LSeaYEVO9GhcSjEG27BDFdYHHWD6C-gJwt1IsZ5ggfgxsC3vakfay3aQbRaoQycvk_lYzJA-xwcqJodOx6OkeSPm64Whq2njbyQ4YRUsvLo6DbWm5bZ6vVd4INTetwJErjMMn6XMcHp3Oont6UetuMeg_VdhPcnI58ew1DjbDAlpBk-B5z-MAMxPrhQYLFgsqOU8YdSQD4ddTD7OW9NUyjvNqcQAvoJIYfUCsGw3hTG9VXG7TyJQJQ_I5oq7_5gHLcuaHJn5Pzfq47Tql88UnoQZKSw4FcfEDP7uXNXAdg5edc4wnog8LMeIa6WqYXfnjy5rIjLnhJcq-6Ot4KIOVjNL3teDLCe9A7fv7tdLSJiCf4Pz-jEjRS_Z0pdHdwyFihUWcl578JKHAHlj4B0CY9zXSmTdNeY-LofKP1vaFX8Ct6sQsYOJB-O3oOqfxeVHNRYD6liPWnLcFmyBFR9qV-XpSCR-PnxwBUJ9s0v_tCpHfwDMO6T8jf72OxZ-H8IA",
    "refresh_token": "def502005aa00689b542002eb9f23e83351ffeb309d6b804023b533804d36652ad1a8458fe7bf14e25043b28c2b842938dd6b056202bddd568d6bdccdd000d913c76cfd281b7a1df56675c4f04f56f4b63b68011d13a5e363bf64de44931faabf22b672f63cbe215f664f52c1830d217f39c3688adaec49f97f95652777e9f4bab5184c6d51c0ae93ad0f3b64c01c0b22bc67c577c6fa9a4247a8865a6eae9b3f37d1c496e9274e4ae6bb01e830461bde27e562f3a31f420bd34cb1d30456336c85cc40dcf8290b74d7661ade84efe81cfa3fc623c78bb3f6ca385dcc60278e6be10c9127206ca55144f7d419e87b89e19d48e159b790d66d3d65860dacc87f7b9806e770eff8436c87c18cdfa75a2e4e7cc1430876b78f647608189214fc2daa465758e6c51909a08bd1aa868978821144b74f65a124d84195d1b0cbafdbca9c664ac082b1f2bd14aa728d740a7b17073413db6af179940d79de0b43ada6f01ee56795a"
}

请求令牌过程中有几个需要注意的点:

1 - 采用 postman 之类的工具请求时,用 application/x-www-form-urlencode,即 form data 形式提交,否则会返回 unsupported_grant_type 的错误。

2 - 如果出现 invalid_credentials 错误,修改提交参数,默认未修改的情况下,username 值使用电子邮件地址,即类似以 makeit@makeit.vip 作为 username 的值 ( 当然,可以自定义用户名字段, 查看上面所述中《更新模型》这一块的内容 )

3 - 该方式,默认情况下,发放的访问令牌是长期有效的,如果需要修正时间,请查看 《Laravel 5.8 API 开发实战(三)》


请求作用域

使用密码授权机制时,请求参数中若携带了 scope 参数,且值为 * 的话,令牌实例中的 can 方法将一直都返回 true 的状态;这种作用域的授权只能分配给使用 password 授权的令牌。

颁发访问令牌

使用授权码时,客户端的应用程序会将用户重定向我们的授权服务器,授权服务器返回信息进行询问用户,是批准还是拒绝该客户端访问授权令牌(如果对于OAuth的授权流程不清楚的话,可以查看阮一峰《关于 OAuth2.0 的理解》的日志)

管理客户端

很显然,为了方便测试 OAuth2.0 的功能,我们需要生成一个 [ 客户端 ] 来注册自己的应用程序,完成整个授权流程, php artisan passport:client,该命令会创建一个客户端(第三方或用户是无法使用 client 命令的,此处是为了方便测试)。

如上图所示,为这个客户端分配了 user 表中 id = 1 的用户;若该 user 表为空的话,可以运行如下命令完成用户创建。

php artisan tinker
App\User::create(['name' => 'makeit', 'email' => 'makeit@makeit.vip', 'password' => bcrypt('123456')]);

虽然用户或者第三方无法使用 client 命令进行客户端创建,但是 Laravel 提供了一系列的接口,我们也就不用费时费事的去编写控制器来操作了,当然,要管理这些客户端,还是需要添加,删除等相关的管理页面的;此处我们为了方便测试,就不进行页面展示了,我们只用 postman,resetlet 等工具来进行接口测试,但是这些 API 由 web 与 auth 两个中间件的保护,正常情况下只能从应用程序内部进行调用,外部是不允许调用的,所以需要进行一些准备工作的,本篇就说一下跨域问题的解决,其它的准备工作就先不赘述了。

CORS 跨域

composer require barryvdh/laravel-cors,执行该命令,安装 laravel-cors


config/app.php 文件内的 alials 中,添加如下内容,注册相应的服务:

'CROS' => Barryvdh\Cors\HandleCors::class

修改 app/Http/Kernel.php 文件,此处可分全局和局部使用两种方式,全局使用则将该服务添加到 $middleware 内容中,局部的则添加至 $middlewareGroups 中的 web / api 中都可以。

<?php

namespace App\Http;

use Barryvdh\Cors\HandleCors;
use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel {
    protected $middleware = [
        ......
       HandleCors::class
    ];
    ......
}

执行 php artisan vendor:publish --provider="Barryvdh\Cors\ServiceProvider" 发布 cors 的配置。

发布配置后,在 config 目录下生成了 cors.php 配置文件,可以在 allowedHeaders 自定义 header,比如 Content-Type,X-Requested-With。白名单或者确定可访问的域名,在 allowedOrigins 添加即可,自行配置。

至此,oAuth 2.0 密码授权令牌的实现就完成了,另外还讲述了相关的客户端管理及其跨域的一些问题,三四篇下来,基本上 API 开发的起步工作算是完成了,从最初《Laravel 5.8 API 开发实战(一)》跑通无授权的接口,至《Laravel 5.8 API 开发实战(二)》实现 jwt-auth 的认证,再到《Laravel 5.8 API 开发实战(三)》实现无感刷新 token,再到当前实现 oAuth 2.0 密码授权,总结整理了 API 开发的前期准备工作,后续将结合开发实际,说说具体的功能点,比如采用 RabbitMQ,结合 QQ 邮箱,实现注册的邮件的异步发送,加快响应速度之类的 ......

相关推荐

当Frida来“敲”门(frida是什么)

0x1渗透测试瓶颈目前,碰到越来越多的大客户都会将核心资产业务集中在统一的APP上,或者对自己比较重要的APP,如自己的主业务,办公APP进行加壳,流量加密,投入了很多精力在移动端的防护上。而现在挖...

服务端性能测试实战3-性能测试脚本开发

前言在前面的两篇文章中,我们分别介绍了性能测试的理论知识以及性能测试计划制定,本篇文章将重点介绍性能测试脚本开发。脚本开发将分为两个阶段:阶段一:了解各个接口的入参、出参,使用Python代码模拟前端...

Springboot整合Apache Ftpserver拓展功能及业务讲解(三)

今日分享每天分享技术实战干货,技术在于积累和收藏,希望可以帮助到您,同时也希望获得您的支持和关注。架构开源地址:https://gitee.com/msxyspringboot整合Ftpserver参...

Linux和Windows下:Python Crypto模块安装方式区别

一、Linux环境下:fromCrypto.SignatureimportPKCS1_v1_5如果导包报错:ImportError:Nomodulenamed'Crypt...

Python 3 加密简介(python des加密解密)

Python3的标准库中是没多少用来解决加密的,不过却有用于处理哈希的库。在这里我们会对其进行一个简单的介绍,但重点会放在两个第三方的软件包:PyCrypto和cryptography上,我...

怎样从零开始编译一个魔兽世界开源服务端Windows

第二章:编译和安装我是艾西,上期我们讲述到编译一个魔兽世界开源服务端环境准备,那么今天跟大家聊聊怎么编译和安装我们直接进入正题(上一章没有看到的小伙伴可以点我主页查看)编译服务端:在D盘新建一个文件夹...

附1-Conda部署安装及基本使用(conda安装教程)

Windows环境安装安装介质下载下载地址:https://www.anaconda.com/products/individual安装Anaconda安装时,选择自定义安装,选择自定义安装路径:配置...

如何配置全世界最小的 MySQL 服务器

配置全世界最小的MySQL服务器——如何在一块IntelEdison为控制板上安装一个MySQL服务器。介绍在我最近的一篇博文中,物联网,消息以及MySQL,我展示了如果Partic...

如何使用Github Action来自动化编译PolarDB-PG数据库

随着PolarDB在国产数据库领域荣膺桂冠并持续获得广泛认可,越来越多的学生和技术爱好者开始关注并涉足这款由阿里巴巴集团倾力打造且性能卓越的关系型云原生数据库。有很多同学想要上手尝试,却卡在了编译数据...

面向NDK开发者的Android 7.0变更(ndk android.mk)

订阅Google官方微信公众号:谷歌开发者。与谷歌一起创造未来!受Android平台其他改进的影响,为了方便加载本机代码,AndroidM和N中的动态链接器对编写整洁且跨平台兼容的本机...

信创改造--人大金仓(Kingbase)数据库安装、备份恢复的问题纪要

问题一:在安装KingbaseES时,安装用户对于安装路径需有“读”、“写”、“执行”的权限。在Linux系统中,需要以非root用户执行安装程序,且该用户要有标准的home目录,您可...

OpenSSH 安全漏洞,修补操作一手掌握

1.漏洞概述近日,国家信息安全漏洞库(CNNVD)收到关于OpenSSH安全漏洞(CNNVD-202407-017、CVE-2024-6387)情况的报送。攻击者可以利用该漏洞在无需认证的情况下,通...

Linux:lsof命令详解(linux lsof命令详解)

介绍欢迎来到这篇博客。在这篇博客中,我们将学习Unix/Linux系统上的lsof命令行工具。命令行工具是您使用CLI(命令行界面)而不是GUI(图形用户界面)运行的程序或工具。lsoflsof代表&...

幻隐说固态第一期:固态硬盘接口类别

前排声明所有信息来源于网络收集,如有错误请评论区指出更正。废话不多说,目前固态硬盘接口按速度由慢到快分有这几类:SATA、mSATA、SATAExpress、PCI-E、m.2、u.2。下面我们来...

新品轰炸 影驰SSD多款产品登Computex

分享泡泡网SSD固态硬盘频道6月6日台北电脑展作为全球第二、亚洲最大的3C/IT产业链专业展,吸引了众多IT厂商和全球各地媒体的热烈关注,全球存储新势力—影驰,也积极参与其中,为广大玩家朋友带来了...