Laravel+Next.js开发Shopify应用:自定义XSRF保护实现合理性问询
自行实现的XSRF保护是否安全可靠?
我正在使用Next.js作为前端、Laravel作为API开发一款Shopify应用,采用Shopify PHP API库处理OAuth认证,未使用Laravel内置认证功能。我需要为/login等特定路由添加XSRF保护,目前已自行完成了一套实现,现希望确认该实现是否安全可靠。以下是我的具体实现步骤:
Laravel API端实现步骤
- 在
app/Http/Kernel.php中,为API路由组添加Laravel会话中间件,以便为访问API的每个用户存储会话:
protected $middlewareGroups = [ 'web' => [ // ... ], 'api' => [ \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, // 已取消注释 \Illuminate\Session\Middleware\StartSession::class, // 新增 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, ], ];
此操作已成功存储laravel_session Cookie。
- 在
routes/api.php中创建路由,用于生成随机令牌并存储到用户会话中,同时重新生成用户会话ID(我认为这可防范会话固定攻击),并为所有子域名设置XSRF-TOKENCookie(httpOnly=false,以便后续通过JS附加到请求头):
// 生成XSRF令牌并存储到用户会话(laravel_session) Route::get('/xsrf-token', function(Request $request) { $xsrfToken = md5(uniqid(mt_rand(), true)); $request->session()->put('XSRF', $xsrfToken); $request->session()->regenerate(); if(!$request->session()->get('XSRF')) { return response()->json(['message' => '无法设置XSRF令牌。'], 403); } return response()->json(['message' => 'success'], 200)->withCookie( 'XSRF-TOKEN', $xsrfToken, 120, '/', config('session')['domain'], true, false ); });
注:修正了原代码中response()->json(['message', 'success'])的格式错误,应为键值对格式
- 创建中间件函数验证令牌有效性:若前端通过JS附加到请求头的令牌与会话中存储的令牌一致,则请求有效,可继续执行:
public function handle(Request $request, Closure $next) { $headerXsrfToken = request()->header('x-xsrf-token'); $sessionXsrfToken = request()->session()->get('XSRF'); if( !$headerXsrfToken || !$sessionXsrfToken || strcmp($headerXsrfToken, $sessionXsrfToken) !== 0 ) { return response()->json(['message' => '无效或缺失XSRF令牌'], 403); } $request->session()->forget('XSRF'); $response = $next($request); return $response->withoutCookie('XSRF-TOKEN'); }
- 创建测试路由:
Route::get('test-xsrf', function() { return response('XSRF令牌验证通过!'); })->middleware('xsrf.check');
Next.js前端实现步骤
- 点击按钮时调用
handleValidateCSRFToken函数,该函数先调用/api/xsrf-token设置XSRF-TOKENCookie,再向受保护路由发起请求(axios会自动将XSRF-TOKENCookie值附加到x-xsrf-token请求头):
import axios from "axios"; const API_URL = "https://devapi.customerlift.app"; const Test = () => { const handleValidateCSRFToken = async () => { // 获取CSRF令牌Cookie const resA = await axios.get(`${API_URL}/api/xsrf-token`, { withCredentials: true, // 允许发送和设置Cookie }); console.log(resA); // 向受XSRF令牌保护的路由发起请求(axios会自动从XSRF-TOKEN Cookie中取值设置x-xsrf-token请求头) const resB = await axios.get(`${API_URL}/api/test-xsrf`, { withCredentials: true, }); console.log(resB.data); }; return ( <button className="m-5 bg-blue-500 text-white p-3" onClick={handleValidateCSRFToken} > 验证XSRF令牌 </button> ); }; export default Test;
目前所有功能看似正常,但这是我首次自行实现XSRF保护,希望有人能帮我排查是否存在问题。
内容的提问来源于stack exchange,提问作者Danny Adams
相关产品推荐
相关产品推荐

