Laravel Lighthouse GraphQL中如何让@guard在@validator之前执行?
解决Lighthouse中鉴权先于验证执行的问题
方案一:调整@Guard指令的执行优先级
Lighthouse的指令执行顺序由$priority属性控制,数值越大越先执行。默认情况下@validator的优先级高于@guard,我们可以自定义一个高优先级的Guard指令来覆盖默认行为:
- 创建自定义Guard指令:
<?php namespace App\GraphQL\Directives; use Nuwave\Lighthouse\Auth\Directives\GuardDirective; class PrioritizedGuardDirective extends GuardDirective { // 设置更高优先级,确保比@validator先执行(默认@validator优先级为100) public static int $priority = 200; }
- 在
lighthouse.php配置文件中注册该自定义指令:
'directives' => [ 'guard' => App\GraphQL\Directives\PrioritizedGuardDirective::class, ],
后续使用@guard指令时,会优先于@validator完成鉴权,再执行验证逻辑。
方案二:将验证逻辑移至Resolver中手动执行
放弃使用@validator指令,改为在Resolver内先完成鉴权,再手动触发验证规则:
- 定义输入验证规则(可放在独立的Request类中):
<?php namespace App\GraphQL\Requests; use Illuminate\Foundation\Http\FormRequest; class CreatePostRequest extends FormRequest { public function rules() { return [ 'title' => 'required|string|max:255', 'user_id' => 'required|exists:users,id', ]; } }
- 在Resolver中先鉴权,再执行验证:
<?php namespace App\GraphQL\Resolvers; use App\GraphQL\Requests\CreatePostRequest; use App\Models\Post; use Illuminate\Support\Facades\Auth; use GraphQL\Error\Error; class CreatePostResolver { public function __invoke($root, array $args) { // 先执行鉴权逻辑 if (!Auth::guard('api')->check()) { throw new Error('Unauthorized'); } // 手动触发验证 $request = CreatePostRequest::createFromGlobals(); $request->merge($args['input']); $validatedData = $request->validate(); // 执行业务逻辑 return Post::create($validatedData); } }
- 在GraphQL Schema中移除
@validator指令,指定自定义Resolver:
type Mutation { createPost(input: CreatePostInput!): Post! @guard(with: ["api"]) @resolver(class: "App\\GraphQL\\Resolvers\\CreatePostResolver") }
方案三:通过Pipeline全局调整执行顺序
修改Lighthouse的字段处理Pipeline,将鉴权环节移至验证之前:
- 创建自定义Pipeline工厂类:
<?php namespace App\GraphQL\Pipelines; use Nuwave\Lighthouse\Execution\PipelineFactory; use Nuwave\Lighthouse\Auth\Pipeline\Authorize; use Nuwave\Lighthouse\Validation\Pipeline\Validate; class PrioritizedPipelineFactory extends PipelineFactory { protected function steps(): array { $steps = parent::steps(); // 将鉴权步骤移到验证步骤之前 $authorizePos = array_search(Authorize::class, $steps); $validatePos = array_search(Validate::class, $steps); if ($authorizePos !== false && $validatePos !== false && $authorizePos > $validatePos) { unset($steps[$authorizePos]); array_splice($steps, $validatePos, 0, Authorize::class); } return $steps; } }
- 在
lighthouse.php配置中替换默认的Pipeline工厂:
'execution' => [ 'pipeline_factory' => App\GraphQL\Pipelines\PrioritizedPipelineFactory::class, ],
该方案会全局调整所有字段的执行顺序,确保鉴权优先于验证完成。
内容的提问来源于stack exchange,提问作者amit
相关产品推荐
相关产品推荐

