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

Laravel多域名场景下的用户跨域登录认证问题咨询

解决Laravel多域名应用跨域登录问题

这个问题我之前在处理多域名SaaS应用时碰到过,核心原因是浏览器的同源策略限制了Session Cookie只能在当前域名下生效,导致你在example-A.com登录的用户无法在example-B.com自动获取会话状态。下面是一套完整的解决方案:

首先要让Laravel生成的Session Cookie能在所有目标域名下生效,这需要修改Session配置:

  • 在.env文件中设置顶级域名作为Session域名(注意前面的点):

    SESSION_DOMAIN=.example.com
    

    假设你的三个域名都是example-A.com、example-B.com、example-C.com,它们的顶级域名是example.com,加上前缀点后,Cookie会被所有子域名共享。

  • 打开config/session.php,确认以下配置项:

    'domain' => env('SESSION_DOMAIN', null),
    'same_site' => env('SESSION_SAME_SITE', 'none'),
    'secure' => env('SESSION_SECURE', true),
    
    • same_site=none:允许跨域场景下浏览器传递Cookie(必须配合secure=true)
    • secure=true:要求Cookie仅通过HTTPS传输(生产环境必须开启,本地开发可临时设为false)

2. 自定义跨域登录逻辑

仅配置Cookie还不够,因为你是在example-A.com的后台主动登录其他域名的用户,需要主动同步会话状态到目标域名。可以通过签名URL验证的方式实现:

步骤1:生成跨域登录签名URL

在你的后台登录处理方法中,生成一个带签名的跳转URL,用于目标域名验证用户身份:

public function loginCrossDomainUser(User $user, string $targetDomain)
{
    // 生成过期时间(5分钟内有效)
    $expiresAt = now()->addMinutes(5)->getTimestamp();
    // 生成签名(用APP_KEY确保不可伪造)
    $signature = hash_hmac('sha256', "{$user->id}|{$expiresAt}", config('app.key'));

    // 拼接目标域名的登录验证URL
    $loginUrl = "https://{$targetDomain}/auth/cross-domain-login?user_id={$user->id}&expires={$expiresAt}&signature={$signature}";

    // 跳转到目标域名完成登录
    return redirect()->away($loginUrl);
}

步骤2:在目标域名添加验证路由

在所有需要支持跨域登录的域名的routes/web.php中添加路由:

use App\Http\Controllers\Auth\CrossDomainLoginController;

Route::get('/auth/cross-domain-login', [CrossDomainLoginController::class, 'handle'])->name('cross-domain.login');

步骤3:实现验证登录逻辑

创建CrossDomainLoginController,处理签名验证并完成登录:

namespace App\Http\Controllers\Auth;

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Routing\Controller;

class CrossDomainLoginController extends Controller
{
    public function handle(Request $request)
    {
        // 验证参数是否齐全
        $request->validate([
            'user_id' => 'required|integer',
            'expires' => 'required|integer',
            'signature' => 'required|string',
        ]);

        $userId = $request->user_id;
        $expires = $request->expires;
        $signature = $request->signature;

        // 验证链接是否过期
        if (now()->getTimestamp() > $expires) {
            abort(403, '登录链接已过期,请重新操作');
        }

        // 验证签名是否合法
        $expectedSignature = hash_hmac('sha256', "{$userId}|{$expires}", config('app.key'));
        if (!hash_equals($expectedSignature, $signature)) {
            abort(403, '无效的登录请求,请重试');
        }

        // 查找用户并完成登录
        $user = User::findOrFail($userId);
        Auth::login($user);

        // 跳转到目标域名的首页或指定页面
        return redirect('/');
    }
}

3. 关键注意事项

  • 统一APP_KEY:所有域名的Laravel应用必须使用相同的APP_KEY,否则签名验证会失败(因为签名依赖APP_KEY)。
  • HTTPS强制开启:生产环境必须使用HTTPS,否则SameSite=None的Cookie会被浏览器拒绝。
  • iframe优化体验:如果不想让用户看到跳转过程,可以用iframe加载目标域名的登录验证URL,但需要在目标域名的响应头中设置X-Frame-Options: ALLOW-FROM https://example-A.com(或者更宽松的配置),允许后台域名嵌入。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:08:36