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

Laravel iframe无法存储Cookie:Safari适配及LocalStorage替代方案

解决方案:Safari iframe第三方Cookie问题及Laravel改用LocalStorage认证

一、让Safari存储iframe中第三方站点Cookie的可行方案

  • 使用Storage Access API:这是Safari官方适配第三方Cookie限制的方案,必须通过用户主动交互(如点击按钮)触发权限请求。在b.com的登录逻辑中加入以下处理:
document.getElementById('login-trigger').addEventListener('click', async () => {
  try {
    const accessGranted = await document.requestStorageAccess();
    if (accessGranted) {
      // 权限获取成功后执行登录请求,此时Cookie可正常存储
      await fetch('/login', { method: 'POST', credentials: 'include' });
    }
  } catch (err) {
    // 权限请求失败时,提示用户手动授权或切换方案
  }
});
  • 配置站点关联(Apple App Site Association):若a.com和b.com同属一个主体,可通过配置AASA文件让Safari判定二者为关联站点,从而允许第三方Cookie。需在b.com根目录放置apple-app-site-association文件,包含a.com的域名配置,并在苹果开发者后台完成关联域名备案。
  • 第一方上下文跳转登录:先引导用户从iframe跳转至b.com的独立登录页面(第一方环境),登录完成后再跳转回a.com的iframe。此方式能确保Cookie正常写入,仅用户体验略有折损。

二、Laravel改用LocalStorage实现用户认证

若上述Cookie方案无法满足需求,可通过令牌式认证替代Cookie,将令牌存储在LocalStorage中:

1. 配置Laravel Sanctum令牌认证

  • 安装并初始化Sanctum:
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
  • 修改config/auth.php,将API守卫驱动设为Sanctum:
'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    'api' => [
        'driver' => 'sanctum',
        'provider' => 'users',
    ],
],

2. 编写登录接口返回令牌

在登录控制器中,验证用户后生成并返回PlainText令牌:

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

public function login(Request $request)
{
    $validated = $request->validate([
        'email' => 'required|email',
        'password' => 'required',
    ]);

    if (!Auth::attempt($validated)) {
        return response()->json(['msg' => '登录失败'], 401);
    }

    $token = Auth::user()->createToken('iframe-auth')->plainTextToken;
    return response()->json(['token' => $token]);
}

3. 前端存储令牌到LocalStorage

登录成功后将令牌存入LocalStorage:

fetch('/api/login', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: 'user@example.com', password: 'xxx' })
})
.then(res => res.json())
.then(data => localStorage.setItem('auth_token', data.token));

4. 后续请求携带令牌

所有需要认证的请求,在请求头中携带令牌:

fetch('/api/user', {
  headers: {
    'Authorization': `Bearer ${localStorage.getItem('auth_token')}`
  }
})
.then(res => res.json())
.then(userData => console.log(userData));

5. 注销逻辑处理

注销时删除LocalStorage令牌,并在后端撤销对应令牌:

// 前端清除令牌
localStorage.removeItem('auth_token');

// 后端注销接口
public function logout(Request $request)
{
    $request->user()->currentAccessToken()->delete();
    return response()->json(['msg' => '注销成功']);
}

内容的提问来源于stack exchange,提问作者Mohammad Salehi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 01:45:32