在Laravel中验证第三方JWT(RS256 & JWKS)的教程

在Laravel中验证第三方JWT(RS256 & JWKS)的教程

本教程将指导您如何在laravel应用中验证来自外部身份提供商的rs256签名jwt。我们将利用tymondesigns/jwt-auth包,通过配置jwks获取的公钥、实现自定义认证守卫(guard)来处理令牌解析与签名验证,并将其无缝集成到laravel的认证体系中,从而确保api请求的安全性。

在现代微服务架构和单页应用(SPA)中,使用外部身份提供商(IdP)进行用户认证已成为常见模式。用户通过IdP认证后会获得一个Access Token(通常是JWT),后端API服务需要验证这个JWT以授权访问。本教程将详细介绍如何在Laravel应用中,利用tymondesigns/jwt-auth包以及自定义认证守卫,高效且安全地验证来自第三方IdP的RS256签名的JWT。

1. 获取并配置JWT公钥

验证RS256签名的JWT需要对应的公钥。外部身份提供商通常会通过一个JWKS(JSON Web Key Set)URL(例如 https://{domain}/.well-known/jwks.json)公开其公钥。您需要从这个JWKS URL获取相应的公钥,并将其保存为PEM格式的文件。

步骤:

从JWKS URL获取公钥: 访问您的IdP提供的JWKS URL。通常,JWKS是一个JSON数组,包含一个或多个JSON Web Key (JWK) 对象。您需要根据JWT头部的kid(Key ID)或其他标识符找到匹配的公钥。将JWK中的n(modulus)和e(exponent)字段转换为PEM格式的RSA公钥。市面上有一些工具或库可以帮助您完成这个转换,例如PHP的phpseclib或在线JWK转PEM工具。

保存公钥文件: 将转换后的PEM格式公钥保存到Laravel项目的安全位置,例如 storage/jwt/public.pem。

配置tymondesigns/jwt-auth: 修改config/jwt.php配置文件,指定公钥文件的路径和签名算法。

// config/jwt.phpreturn [    // ...    'keys' => [        'public' => 'file://' . storage_path('jwt/public.pem'),        'private' => null, // 如果只验证,不需要私钥        'passphrase' => null,    ],    'algo' => 'RS256', // 确保与您的IdP使用的算法一致    // ...];

请确保storage/jwt目录存在且可读。

2. 实现自定义JWT认证守卫 (Guard)

Laravel的认证系统允许您定义自定义的认证守卫。我们将创建一个JWTGuard来封装JWT的验证逻辑,包括解析令牌、检查签名和提取用户信息。

创建守卫文件:app/Guard目录下创建JWTGuard.php文件(如果目录不存在,请先创建)。

jwt = $jwt;        $this->request = $request;    }    /**     * 获取当前认证用户。     *     * @return IlluminateContractsAuthAuthenticatable|null     */    public function user()    {        if (!is_null($this->user)) {            return $this->user;        }        // 尝试从请求中获取JWT,并检查其有效性        if ($this->jwt->setRequest($this->request)->getToken() && $this->jwt->check()) {            // 从JWT payload中获取用户标识(通常是'sub' claim)            $id = $this->jwt->payload()->get('sub');            // 根据IdP返回的用户信息创建或查找本地用户实例            // 这里我们创建一个简单的User实例,您可以根据需要从数据库查找或设置更多自定义属性            $this->user = new User();            $this->user->id = $id;            // 如果需要,可以从JWT payload中提取更多自定义声明并设置到用户模型            // $this->user->email = $this->jwt->payload()->get('email');            return $this->user;        }        return null;    }    /**     * 验证用户凭据(在本场景中不使用,因为我们通过JWT验证)。     *     * @param array $credentials     * @return bool     */    public function validate(array $credentials = [])    {        // 对于JWT验证,此方法通常留空或返回false        return false;    }}

自定义用户模型:为了让JWTGuard能够返回一个Authenticatable的用户实例,您可能需要创建一个简单的User模型,或者确保您现有的User模型实现了IlluminateContractsAuthAuthenticatable接口。

id;    }    /**     * Get the password for the user.     *     * @return string     */    public function getAuthPassword()    {        return ''; // 对于JWT认证,密码通常不直接存储或使用    }    /**     * Get the "remember me" token value.     *     * @return string     */    public function getRememberToken()    {        return null; // 对于无状态JWT认证,不需要remember token    }    /**     * Set the "remember me" token value.     *     * @param  string  $value     * @return void     */    public function setRememberToken($value)    {        //    }    /**     * Get the column name for the "remember me" token.     *     * @return string     */    public function getRememberTokenName()    {        return '';    }}

3. 注册并激活自定义守卫

完成JWTGuard的创建后,需要将其注册到Laravel的认证系统中,并在config/auth.php中配置使用。

在AuthServiceProvider中注册:修改app/Providers/AuthServiceProvider.php的boot方法。

 'AppPoliciesModelPolicy',    ];    /**     * Register any authentication / authorization services.     *     * @return void     */    public function boot()    {        $this->registerPolicies();        // 扩展Laravel的认证系统,注册自定义的'jwt-auth'守卫        $this->app['auth']->extend(            'jwt-auth', // 守卫的驱动名称            function ($app, $name, array $config) {                $guard = new JWTGuard(                    $app['tymon.jwt'], // 获取tymon.jwt实例                    $app['request']    // 获取当前请求实例                );                // 确保每次请求时,守卫都能获取到最新的请求实例                $app->refresh('request', $guard, 'setRequest');                return $guard;            }        );    }}

在config/auth.php中配置:将新的jwt守卫添加到guards配置项中。

 [        'guard' => 'web', // 默认守卫,可以根据需要调整        'passwords' => 'users',    ],    'guards' => [        'web' => [            'driver' => 'session',            'provider' => 'users',        ],        // ... 其他守卫        'jwt' => [ // 定义您的JWT守卫            'driver' => 'jwt-auth', // 对应AuthServiceProvider中extend的驱动名称            'provider' => 'users'   // 可以是任何有效的provider,这里我们使用默认的users        ],    ],    'providers' => [        'users' => [            'driver' => 'eloquent',            'model' => AppModelsUser::class,        ],        // ...    ],    // ...];

4. 在路由中使用认证守卫

现在,您可以通过Laravel的路由中间件来保护您的API端点,确保只有携带有效JWT的请求才能访问。

get('/user', function () {    // 只有携带有效JWT并成功通过'jwt'守卫认证的请求才能到达这里    return Auth::user(); // 返回当前认证用户实例});// 您也可以在控制器构造函数中使用// public function __construct()// {//     $this->middleware('auth:jwt');// }

当请求到达/user路由时,auth:jwt中间件会激活JWTGuard。如果请求头中包含有效的Bearer Token,JWTGuard将对其进行解析、签名验证,并根据sub声明设置认证用户。

5. 扩展与注意事项

声明和范围验证: JWTGuard中的$this->jwt->check()会验证JWT的格式、签名和基本的标准声明(如过期时间exp)。如果需要验证更具体的声明(如iss、aud、nbf)或自定义的应用程序权限(scopes),您可以在JWTGuard的user()方法中,在$this->jwt->check()之后,通过$this->jwt->payload()获取所有声明,然后添加额外的逻辑进行验证。对于Scopes,通常会创建一个独立的中间件来处理。错误处理: 当前的实现在JWT验证失败时会返回null用户,导致Laravel抛出未经认证的HTTP响应(401 Unauthorized)。您可以根据需要捕获tymon/jwt-auth抛出的异常(例如TokenExpiredException, TokenInvalidException等),并返回更详细的错误信息。公钥管理: 如果您的IdP会定期轮换JWKS中的公钥,您需要建立一个机制来自动或手动更新storage/jwt/public.pem文件。例如,可以编写一个Artisan命令,定期从JWKS URL获取最新的公钥并更新本地文件。性能考量: 每次请求都从磁盘读取公钥文件可能会有轻微的性能开销。在生产环境中,可以考虑将公钥内容缓存到内存或OPcache中,以减少文件I/O。

通过以上步骤,您已经成功地在Laravel应用中构建了一个健壮的机制,用于验证来自外部身份提供商的RS256签名的JWT。这不仅增强了API的安全性,也使其能够与复杂的身份认证生态系统无缝集成。

以上就是在Laravel中验证第三方JWT(RS256 & JWKS)的教程的详细内容,更多请关注php中文网其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1341200.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月13日 04:31:03
下一篇 2025年12月13日 04:31:12

相关推荐

  • 解决phpMyAdmin导出导入时SET time_zone错误:一份详细教程

    针对phpMyAdmin数据库导出后,在导入时遇到的#1298 – Unknown or incorrect time zone: ‘+00:00’错误,本教程提供了详细的解决方案。文章将深入分析错误成因,并提供通过调整phpMyAdmin导出设置、手动修改SQL…

    好文分享 2025年12月13日
    000
  • PHP与MySQL交互:正确选择随机行并避免mt_rand()误用

    本文旨在解决PHP中将`mt_rand()`函数错误地直接嵌入MySQL查询的问题,并指导开发者如何正确地从数据库中选择随机行。文章将详细解释PHP与SQL的执行上下文差异,分析常见错误及其局限性,并提供使用MySQL内置`RAND()`函数及针对大型数据集的优化方案,确保代码的健壮性与性能。 在开…

    2025年12月13日 好文分享
    000
  • 使用array_filter在PHP多维数组中进行多条件搜索

    本文深入探讨了在php中如何高效地从多维数组中查找符合特定多重条件的数据。针对`array_search`无法处理复杂多条件查询的局限性,我们详细介绍了`array_filter`函数的使用方法。通过匿名函数结合`use`关键字,`array_filter`能够灵活地对数组中的每个元素应用自定义逻辑…

    2025年12月13日
    000
  • PHP日期处理教程:巧用DateTime类高效提取月份信息

    本教程旨在解决php中处理用户提交日期时,通过繁琐的条件判断来确定月份的常见问题。我们将深入探讨如何利用php内置的`datetime`类,以一种更简洁、高效且健壮的方式解析日期字符串,并直接提取出所需的月份信息,从而避免复杂的字符串比较和冗长的`if/else`语句链,提升代码的可读性和维护性。 …

    2025年12月13日
    000
  • 获取Laravel中分类ID及处理父子关系的高效策略

    本文旨在提供在laravel应用中高效获取分类id并处理父子分类关系的教程。我们将首先探讨如何利用`pluck()`和`wherein()`方法解决从父分类集合中提取id并查询其子分类的问题,然后深入讲解如何通过定义eloquent模型间的自引用一对多关系,实现更优雅、可维护的分类数据检索方式,以构…

    2025年12月13日
    000
  • 通过AJAX与PHP cURL实现前端事件追踪与API交互

    本文详细介绍了如何通过JavaScript的AJAX请求触发后端PHP cURL POST操作,实现前端事件(如表单提交)的数据捕获与转发至外部API。教程涵盖了前端AJAX数据序列化、后端PHP接收数据并使用cURL发送POST请求到第三方服务(如ActiveCampaign)的完整流程,并提供了…

    2025年12月13日
    000
  • 怎么给php加密源码_给php加密源码算法与保护技巧【技巧】

    保护PHP代码可通过加密与混淆手段实现。一、使用phpjiami等工具将代码Base64编码并结合eval执行,设置变量名混淆后部署加密文件。二、采用ionCube或Zend Guard将源码编译为字节码,需在安装对应Loader的服务器运行。三、用AES/RSA加密代码,运行时通过远程获取密钥动态…

    2025年12月13日
    000
  • php源码功能怎么移植_php源码功能移植适配与测试方法【指南】

    首先分析源码结构与依赖,确认Composer配置、入口文件引用及PHP版本;再搭建匹配的目标环境,安装对应PHP版本并启用必要扩展;接着迁移源码文件,保持目录结构完整并调整环境参数;随后处理兼容性问题,替换废弃函数、修复命名空间与语法冲突;最后通过单元测试与手动验证确保功能一致。 如果您需要将某个P…

    2025年12月13日
    000
  • 如何使用PHP获取数码相机快门次数(Shutter Count)

    获取数码照片的快门次数(Shutter Count)是一个常见需求,但通过PHP的exif_read_data()函数直接获取往往面临挑战,因为该信息通常存储在制造商专有的MakerNote区域。本文将深入探讨这一问题,解释MakerNote的特性,并通过ExifTool演示其内部结构,最终提供使用…

    2025年12月13日
    000
  • PHP PDO 调用 IBM i QCMDEXC 程序的参数绑定与高级策略

    本文旨在解决在 php pdo 环境下调用 ibm i 的 `qcmdexc` 存储过程时,处理带引号参数绑定的复杂性。由于 `qcmdexc` 仅接受一个命令字符串参数,文章详细阐述了如何构建并安全地绑定该命令字符串,包括内部参数的定界与转义。此外,文章还介绍了两种更强大、更灵活的替代方案:利用 …

    2025年12月13日
    000
  • 理解PHP与HTML交互:为何需要Web服务器及如何搭建开发环境

    本文深入探讨了在没有web服务器(如apache或nginx)和php解释器的情况下,直接将html与php文件链接并执行的可行性问题。我们将解释为何这种直接链接会导致php文件被下载而非执行,并提供搭建必要开发环境(如使用xampp)以实现php代码正确运行和未来数据库集成的专业指导。 PHP与H…

    2025年12月13日
    000
  • Laravel深度调用中抛出自定义验证异常并统一响应

    在Laravel应用中,当业务逻辑需要在深层嵌套函数中进行自定义验证,并希望像内置验证失败一样,直接向前端(尤其是AJAX请求)返回统一的HTTP 422 JSON错误响应时,传统方法往往需要在调用链中层层传递错误状态。本文将介绍如何通过手动抛出`IlluminateValidationValida…

    2025年12月13日
    000
  • jQuery AJAX发送FormData到PHP:正确的数据传输实践

    本文详细探讨了使用jQuery AJAX将FormData对象发送到PHP后端时常见的陷阱与正确方法。核心在于避免将FormData对象封装在额外的JavaScript对象中,并确保`contentType: false`和`processData: false`设置正确。通过正确的配置,PHP后端…

    2025年12月13日
    000
  • PHP Memcache 精准缓存项管理:删除与更新策略

    本文旨在提供一套在PHP中使用Memcache精准管理缓存项的教程。我们将探讨如何通过`Memcache::delete()`配合`Memcache::add()`或`Memcache::set()`方法来清除并更新特定缓存项,而非执行全量刷新。文章将详细阐述`add()`与`set()`之间的关键…

    2025年12月13日
    000
  • 防止PHP表单在页面加载或刷新时自动提交的教程

    本教程详细介绍了如何解决PHP表单在页面首次加载或刷新时自动提交数据的问题。核心解决方案是采用POST-Redirect-GET(PRG)模式,通过在数据处理成功后执行服务器端重定向,有效阻止浏览器在刷新时重复提交POST请求,从而优化用户体验并避免数据重复插入。 理解问题:为何表单会重复提交? 在…

    2025年12月13日
    000
  • php网站源码怎么修改编辑_修改编辑php网站源码技巧【技巧】

    首先选择合适的代码编辑器打开PHP项目,定位需修改文件并编辑内容;接着理解程序结构与变量逻辑,确保不破坏数据流和功能调用;最后安全修改输出内容,直接调整echo或print语句中的HTML或文本,保留原有逻辑完整。 如果您需要对现有的PHP网站源码进行修改和编辑,以实现功能调整或内容更新,可以通过多…

    2025年12月13日
    000
  • 在Yii2表单配置中插入自定义文本标签或标题

    本教程详细阐述如何在yii2的动态表单配置数组中,正确地插入非输入型的文本标签或章节标题,以增强表单的可读性和组织性。文章将通过示例代码演示如何构建此类配置项,并重点强调前端渲染逻辑对这些特殊标签的处理方式,确保它们能被正确识别和展示。 引言 在开发复杂的Web表单时,除了各种输入字段外,我们经常需…

    2025年12月13日
    000
  • 在YARA规则中匹配PHP动态函数调用:应对字符串拼接混淆

    本文旨在探讨在yara规则中有效匹配php中通过字符串拼接进行混淆的动态函数调用,特别是`gzinflate(base64_decode())`模式。文章分析了php字符串拼接的挑战,并提供了多种yara规则匹配策略,包括使用灵活的正则表达式、结合关键词与上下文以及处理内部拼接模式,旨在提高检测的鲁…

    2025年12月13日
    000
  • php怎么打开源码_php打开源码编辑器与查看法【教程】

    可通过文本编辑器、IDE、命令行、Web服务器或版本控制系统打开PHP源码。一、用记事本等工具快速查看;二、使用PhpStorm等IDE进行智能编辑;三、在终端用cat或less命令浏览;四、将文件放入XAMPP等服务器环境运行测试;五、通过git clone获取项目并查看完整结构及修改记录。 如果…

    2025年12月13日
    000
  • 二开php怎么解密_用PHP分析二次开发加密逻辑并解密教程【技巧】

    1、识别加密类型,查看eval(gzinflate、base64_decode等函数及字符串替换逻辑;2、使用PHP美化工具格式化解析结构;3、将eval替换为echo输出解码后源码;4、通过调试运行环境捕获内存中还原的明文代码;5、利用正则批量替换混淆的变量函数名,恢复逻辑可读性。 如果您在进行P…

    2025年12月13日
    000

发表回复

登录后才能评论
关注微信