Laravel 8 API 如何将JWTAuth认证用户ID填充为帖子user_id字段
报错根因
触发1364错误的核心原因是新增帖子的SQL语句缺失user_id字段赋值:
- 当前代码直接拿全量请求参数
$request->all()传给Post::create(),既没有从认证上下文取当前登录用户的ID做自动赋值,也没有隔离前端可能恶意传入的user_id、likes这类敏感字段 posts表的user_id是非空无默认值的字段,插入时缺值就会触发数据库报错- 原代码还存在两处隐藏逻辑问题:
- 标题唯一性校验规则的表名写错:
unique:categories是校验分类表的字段唯一性,和帖子表无关 - tags校验规则
null|string逻辑存在漏洞:当tags入参为null时,后续explode(",", $request->tags)会触发PHP运行时错误
- 标题唯一性校验规则的表名写错:
安全修正方案
先做好模型批量赋值防护
在Post模型中配置$fillable白名单,仅允许指定字段被批量赋值:// app/Models/Post.php protected $fillable = [ 'category_id', 'title', 'body', 'picture', 'study_time', 'tags', 'user_id', // 仅用于手动赋值,不会从前端入参读取 ];改造store方法逻辑,彻底隔绝越权入参风险
不使用$request->all()全量取数,主动只拉取业务允许前端传入的字段,再从JWTAuth认证上下文取当前用户ID手动赋值,从根源上杜绝前端篡改user_id、likes这类敏感字段的可能。修正后完整代码如下:// 仅提取前端允许传入的字段,自动过滤掉user_id、likes、id这类敏感参数 $data = $request->safe()->only([ 'category_id', 'title', 'body', 'picture', 'study_time', 'tags' ]); $validator = Validator::make($data, [ 'category_id' => 'required|exists:categories,id', 'title' => 'required|max:100|unique:posts', // 修正原规则的表名错误 'body' => 'required', 'picture' => 'required', 'study_time' => 'required', 'tags' => 'nullable|string', // 用Laravel内置nullable规则替代原null|string的写法 ]); if ($validator->fails()) { return response()->json([ 'error' => $validator->errors(), 'msg' => 'Validation Error' ], 422); } // 从认证上下文获取用户ID,完全不受前端请求参数影响 $data['user_id'] = JWTAuth::user()->id; // 处理标签逻辑,兼容tags为空的场景 $tags = $request->tags ? explode(",", $request->tags) : []; $post = Post::create($data); $post->tag($tags); return response()->json([ 'username' => JWTAuth::user()->username, 'post' => $post ], 201);效果说明
就算前端在请求里恶意传入user_id=1(管理员账号ID)、likes=10000这类参数,因为我们只通过only()拉取业务允许的字段,这些恶意参数根本不会进入最终的数据库写入流程,完全实现user_id自动赋值、隔绝前端篡改的目标。
内容的提问来源于stack exchange,提问作者calisa
相关产品推荐
相关产品推荐

