Laravel跨应用API登录问题求助:POS系统无法登录库存系统
问题分析与解决方案
问题根源
- 跨应用会话不共享:Laravel默认每个应用的Session独立存储,POS通过Http客户端调用库存API时,
auth()->login($user)仅在API请求的临时会话中生效,无法同步到用户浏览器的库存系统会话。 - 重定向无效:API返回的
redirect('/dashboard')被POS的Http客户端接收,但无法将库存系统的会话Cookie写入用户浏览器,导致用户直接访问库存页面时无有效会话,被重定向到登录页。
解决方案
方案一:共享Session(适合同/子域名场景)
通过配置两个应用共享Session存储,让用户在POS登录的会话能同步到库存系统。
1. 统一Session配置
在两个应用的.env文件中设置相同的Session参数:
SESSION_DRIVER=redis SESSION_DOMAIN=.yourdomain.com # 例如pos.yourdomain.com和inventory.yourdomain.com共享根域名 SESSION_LIFETIME=120 APP_KEY=相同的APP_KEY值 # 两个应用必须使用相同的APP_KEY
确保两个应用连接到同一个Redis实例,Redis配置一致。
2. 修改POS跳转逻辑
替换POS控制器的inventoryLogin方法,生成带签名的跳转链接,直接引导用户浏览器到库存系统的验证路由:
public function inventoryLogin() { $payload = [ 'email' => auth()->user()->email, 'role' => auth()->user()->role, 'timestamp' => time(), ]; // 生成签名防止请求篡改 $signature = hash_hmac('sha256', http_build_query($payload), config('app.key')); $payload['signature'] = $signature; return redirect()->to('http://inventory.sys/login/verify-pos?' . http_build_query($payload)); }
3. 库存系统添加验证路由
在库存系统的web.php中添加路由(不要放在api.php,需要处理浏览器会话):
Route::get('login/verify-pos', function(Request $request) { $rules = [ 'email' => 'email|required|max:300', 'role' => 'required|max:300', 'timestamp' => 'required|integer|max:' . (time() + 300), // 限制5分钟内有效 'signature' => 'required', ]; $validator = Validator::make($request->all(), $rules); if ($validator->fails()) { return redirect('/login')->withErrors($validator); } // 验证签名合法性 $payload = $request->only(['email', 'role', 'timestamp']); $expectedSignature = hash_hmac('sha256', http_build_query($payload), config('app.key')); if (!hash_equals($expectedSignature, $request->signature)) { return redirect('/login')->withErrors(['message' => '无效的请求签名']); } if ($request->role !== "Administrator") { return redirect('/login')->withErrors(['message' => '无权限访问']); } $user = User::where('email', $request->email)->firstOrFail(); auth()->login($user); return redirect('/dashboard'); });
方案二:JWT/Passport单点登录(适合跨域名场景)
通过Laravel Passport实现OAuth2认证,POS获取库存系统的令牌后,引导用户到库存系统验证令牌并登录。
1. 库存系统配置Passport
安装并配置Laravel Passport,创建密码授权客户端,记录client_id和client_secret。
2. POS获取令牌并跳转
修改POS控制器的inventoryLogin方法:
public function inventoryLogin() { $response = Http::asForm()->post('http://inventory.sys/oauth/token', [ 'grant_type' => 'password', 'client_id' => config('services.inventory.client_id'), 'client_secret' => config('services.inventory.client_secret'), 'username' => auth()->user()->email, 'password' => auth()->user()->password, // 确保两个应用密码加密方式一致 'scope' => '', ]); if ($response->successful()) { $token = $response->json()['access_token']; return redirect()->to('http://inventory.sys/login/verify-jwt?token=' . $token); } return redirect()->back()->withErrors(['message' => '登录库存系统失败']); }
3. 库存系统验证令牌并登录
在库存系统的web.php中添加路由:
Route::get('login/verify-jwt', function(Request $request) { $token = $request->get('token'); if (!$token) { return redirect('/login')->withErrors(['message' => '缺少登录令牌']); } try { $user = auth()->guard('api')->setToken($token)->user(); if (!$user || $user->role !== "Administrator") { throw new Exception('无权限访问'); } auth()->login($user); return redirect('/dashboard'); } catch (Exception $e) { return redirect('/login')->withErrors(['message' => $e->getMessage()]); } });
内容的提问来源于stack exchange,提问作者ADORABLE
相关产品推荐
相关产品推荐

