You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel+Next.js开发Shopify应用:自定义XSRF保护实现合理性问询

自行实现的XSRF保护是否安全可靠?

我正在使用Next.js作为前端、Laravel作为API开发一款Shopify应用,采用Shopify PHP API库处理OAuth认证,未使用Laravel内置认证功能。我需要为/login等特定路由添加XSRF保护,目前已自行完成了一套实现,现希望确认该实现是否安全可靠。以下是我的具体实现步骤:

Laravel API端实现步骤

  1. 在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。

  1. 在routes/api.php中创建路由,用于生成随机令牌并存储到用户会话中,同时重新生成用户会话ID(我认为这可防范会话固定攻击),并为所有子域名设置XSRF-TOKEN Cookie(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'])的格式错误,应为键值对格式

  1. 创建中间件函数验证令牌有效性:若前端通过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');
}
  1. 创建测试路由:
Route::get('test-xsrf', function() {
    return response('XSRF令牌验证通过!');
})->middleware('xsrf.check');

Next.js前端实现步骤

  1. 点击按钮时调用handleValidateCSRFToken函数,该函数先调用/api/xsrf-token设置XSRF-TOKEN Cookie,再向受保护路由发起请求(axios会自动将XSRF-TOKEN Cookie值附加到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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 23:05:16