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

Laravel Google登录后会话丢失(购物车清空)问题求助

解决Laravel Socialite登录后购物车会话数据丢失问题

问题场景

使用Laravel Shopping Cart和Laravel Socialite实现登录功能,登录流程本身正常,但存在以下异常:

  • 用户通过表单登录时,购物车及其他会话数据可正常保留
  • 用户通过Google登录后,购物车及页面其他会话数据会被清空
  • 业务需求支持访客或登录用户完成订单,登录方式包含表单登录和Google登录

提供的代码

public function __construct()
{
    $this->middleware('guest')->except('logout');  
}

// Google login
public function redirectToGoogle()
{ 
    return Socialite::driver('google')->stateless()->redirect();
}

// Google callback
public function handleGoogleCallback()
{
    $user = Socialite::driver('google')->stateless()->user();
    
    $this->_registerOrLoginUser($user);
   
    // Return home after login
    return redirect()->route('checkout.index')
        ->with('toast_success',  'Byli jste úspěšně přihlášeni :)');
}

protected function _registerOrLoginUser($data)
{
    $user = User::where('email', '=', $data->email)->first();
    if (!$user) {
        $user = new User();
        $user->name = $data->name;
        $user->email = $data->email;
        $user->provider_id = $data->id;
        $user->avatar = $data->avatar;
        $user->save();
    }
    
    Auth::login($user);
}

/**
 * Show the application's login form.
 *
 * @return \Illuminate\Http\Response
 */
public function showLoginForm()
{
    session()->put('previousUrl', url()->previous());

    return view('auth.login');
}

问题原因

核心原因是你在Socialite调用中使用了stateless()方法:

  • 该方法会禁用Laravel的会话状态管理,导致用户跳转到Google授权时,原有的访客会话无法被持续关联
  • 当Google回调到应用时,请求处于无状态模式,Laravel会生成全新的会话,原会话中的购物车等数据自然丢失
  • 表单登录是在同一会话流程内完成的,因此不会出现会话丢失的问题

解决方案

1. 移除stateless()方法(优先方案)

对于Web应用场景,完全不需要使用stateless(),直接移除该方法即可让Laravel正常维护会话关联:

修改Google登录和回调方法:

// Google login
public function redirectToGoogle()
{ 
    return Socialite::driver('google')->redirect();
}

// Google callback
public function handleGoogleCallback()
{
    $user = Socialite::driver('google')->user();
    
    $this->_registerOrLoginUser($user);
   
    return redirect()->route('checkout.index')
        ->with('toast_success',  'Byli jste úspěšně přihlášeni :)');
}

2. 合并访客购物车到用户购物车(可选增强)

如果你的购物车包支持关联用户(比如bumbummen99/shoppingcart),可以在登录时将访客购物车合并到用户名下,确保数据不丢失:

修改_registerOrLoginUser方法:

protected function _registerOrLoginUser($data)
{
    $user = User::where('email', '=', $data->email)->first();
    if (!$user) {
        $user = new User();
        $user->name = $data->name;
        $user->email = $data->email;
        $user->provider_id = $data->id;
        $user->avatar = $data->avatar;
        $user->save();
    }

    // 保存当前访客购物车内容
    $guestCart = \Cart::content();
    
    Auth::login($user);
    
    // 将访客购物车项添加到用户购物车
    foreach ($guestCart as $item) {
        \Cart::add($item->id, $item->name, $item->qty, $item->price, $item->options);
    }
}

如果是自定义的session购物车,可以在回调时先保存访客数据,登录后恢复:

public function handleGoogleCallback()
{
    // 先获取访客会话中的购物车数据
    $guestCart = session()->get('cart', []);
    
    $user = Socialite::driver('google')->user();
    
    $this->_registerOrLoginUser($user);
    
    // 恢复购物车数据到登录后的会话
    session()->put('cart', $guestCart);
   
    return redirect()->route('checkout.index')
        ->with('toast_success',  'Byli jste úspěšně přihlášeni :)');
}

为什么之前的尝试无效?

你之前尝试的collect(session()->pull('cart'))和session regenerate都无效,是因为stateless()模式下,Google回调请求无法关联到原访客会话,根本无法获取到原会话中的购物车数据,自然无法保留或恢复。

内容的提问来源于stack exchange,提问作者Pepa Zdepa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 10:01:46