PHP开发GraphQL API完整教程(含Laravel Sanctum)

浅明姑娘_3275

浅明姑娘_3275

2026-05-14

947人浏览

原创

结论:laravel + rebing/graphql-laravel 可行,但需手动调用 sanctum::authenticate() 并在 context 中显式注入 user,否则 @can、$context->user 均失效;graphql 不走路由中间件,auth 状态丢失。

php开发graphql api完整教程(含laravel sanctum)

直接说结论:用 Laravel + rebing/graphql-laravel 搭 GraphQL API 是可行的,但和 Sanctum 集成时,Sanctum::authenticate() 不会自动触发,必须手动调用;否则所有 @can 或 $context->user 都是 null。

GraphQL 请求不走 Laravel 中间件,Auth 状态丢失

Laravel 的 Sanctum 中间件(如 auth:sanctum)只对 HTTP 路由生效,而 rebing/graphql-laravel 默认把整个 GraphQL 请求当作一个 POST 到 /graphql,内部用 GraphQLController 处理,绕过了路由级中间件链。

结果就是:Auth::user() 始终为 null,即使请求头带了 Authorization: Bearer xxx 或已设置 Sanctum Cookie。

解决方法是手动在 GraphQL 查询/变更前注入认证逻辑:

  • 在 config/graphql.php 的 'schema' => ['query' => [...]] 之前,加一个全局 middleware 数组,但该包不支持传统中间件写法
  • 更可靠的做法:在每个需要鉴权的 Query 或 Mutation 类的 resolve() 方法开头,显式调用 Sanctum::authenticate($request)
  • 或者统一在 GraphQLController@query 中提前执行(需重写控制器或监听 GraphQLQueryExecuted 事件)

推荐后者——在 app/Http/Controllers/GraphQLController.php 中重写 query():

public function query(Request $request)
{
    // 手动触发 Sanctum 认证,确保 $request->user() 可用
    if ($request->hasHeader('Authorization') || $request->hasCookie('laravel_session')) {
        Sanctum::authenticate($request);
    }
    return parent::query($request);
}

rebing/graphql-laravel 的 context 不自动包含 user

即便 $request->user() 已存在,rebing/graphql-laravel 默认也不会把它塞进 GraphQL 的 $context。这意味着你在 resolver 里写 $context->user 会报错或返回空。

必须在 config/graphql.php 中显式配置 'context' => function (Request $request) { ... }:

'context' => function (Request $request) {
    // 确保 Sanctum 已运行
    if (! $request->user() && $request->hasHeader('Authorization')) {
        Sanctum::authenticate($request);
    }
    return ['user' => $request->user()];
},

注意:这个闭包只在每次请求开始时运行一次,所以要在这里完成所有上下文初始化,比如 DB::connection() 切换、租户识别等也得放这儿。

Laravel Creem Agent
Laravel Creem Agent

Creem 支付商店助理 — 查询订阅、客户、交易、产品,执行心跳检查,管理本地 Laravel支付商店。

下载

使用 @can 指令时权限检查总失败

rebing/graphql-laravel 提供的 @can 指令依赖 Illuminate\Auth\Access\Gate,但它默认从 Auth::user() 取用户——而你刚知道,这个值在 GraphQL 上下文中并不自动可用。

常见错误现象:"Unauthenticated." 或 "This action is unauthorized." 即使 token 正确、用户已登录。

根本原因不是策略写错了,而是 @can 指令没拿到 user 实例。修复方式有两个:

  • 在 context 配置中确保 'user' 键存在且非 null(见上一节)
  • 重写 @can 指令的解析逻辑,在 app/GraphQL/Directives/CanDirective.php 中覆盖 resolveField,从 $context['user'] 而非 Auth::user() 获取主体
  • 更轻量的做法:不用 @can 指令,改在 resolver 内部用 $context['user']->can('edit post') 显式判断,可控性更强

Sanctum Token 过期时间与 GraphQL 长连接场景不匹配

Sanctum 默认 token 是长期有效的(除非手动 token()->delete()),但这对 GraphQL 客户端(尤其是移动端或桌面端)容易造成“静默失效”:用户长时间未操作,token 其实还活着,但 session cookie 可能已被浏览器清理,导致后续请求因 Cookie 缺失而认证失败。

这不是 GraphQL 特有,但 GraphQL 更容易暴露这个问题——因为前端往往复用同一个 client 实例,不会像页面跳转那样自然触发重新登录流程。

建议动作:

  • 前端在收到 401 响应后,主动清空本地 token 并跳转登录页(不要只弹提示)
  • 后端在 GraphQL resolver 中检测 !$context['user'] 时,统一返回自定义错误码(如 UNAUTHENTICATED),避免混用 500 或泛化 message
  • 如果用 Cookie 模式,确保 SESSION_DRIVER=cookie 且 sanctum.stateful 配置包含你的前端域名

真正麻烦的不是怎么配通,而是当 $context['user'] 在某个 resolver 里突然为 null,而你忘了它其实取决于前面那个 Sanctum::authenticate() 是否被调用过——这个点很容易漏在调试时只看策略、不查认证链路。

大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

php laravel php开发

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2023.09.01

10224

6

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.11

6041

5

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.11

2095

5

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

2023.10.23

3788

4

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

2023.10.23

4494

6

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.03

3531

9

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.09

5037

8

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.13

3942

8

sprintf函数用法详解
sprintf函数用法详解

sprintf函数的用法:1、格式化字符串;2、指定输出宽度和精度;3、返回值。更多关于sprintf函数用法详解的内容,大家可以阅读下面的文章。

2023.11.27

11902

4

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
墨刀帮助中心
墨刀帮助中心

共0课时 | 0人学习

MyEclipse学习中心
MyEclipse学习中心

共0课时 | 0人学习

Apache Subversion 官方手册
Apache Subversion 官方手册

共0课时 | 0人学习