liuq 4 months ago
parent
commit
bf8d8c61e0
1 changed files with 97 additions and 22 deletions
  1. 97 22
      server.js

+ 97 - 22
server.js

@@ -101,9 +101,9 @@ function parseCookies(setCookieHeaders) {
 }
 
 // 生成跳转 HTML
-function generateRedirectHTML(cookieData, targetHost, targetDomain, requestId = '', customUrl = null) {
+function generateRedirectHTML(cookieData, targetHost, targetDomain, requestId = '', customUrl = null, homeAssistantData = null) {
   const targetUrl = customUrl || `http://${targetHost}/`;
-  const isHomeAssistant = targetUrl.includes('/auth/authorize');
+  const isHomeAssistant = homeAssistantData !== null;
   
   return `
 <!DOCTYPE html>
@@ -157,6 +157,7 @@ function generateRedirectHTML(cookieData, targetHost, targetDomain, requestId =
             const targetUrl = '${targetUrl}';
             const targetDomain = '${targetDomain}';
             const isHomeAssistant = ${isHomeAssistant};
+            const homeAssistantData = ${homeAssistantData ? JSON.stringify(homeAssistantData) : 'null'};
             
             console.log('========================================');
             console.log('[浏览器端] 自动登录脚本开始执行');
@@ -165,7 +166,8 @@ function generateRedirectHTML(cookieData, targetHost, targetDomain, requestId =
             console.log('[浏览器端] 目标域名:', targetDomain);
             console.log('[浏览器端] Cookie 数量:', cookies.length);
             console.log('[浏览器端] Cookie 详情:', cookies);
-            console.log('[浏览器端] 是否为 Home Assistant 授权流程:', isHomeAssistant);
+            console.log('[浏览器端] 是否为 Home Assistant:', isHomeAssistant);
+            console.log('[浏览器端] Home Assistant 数据:', homeAssistantData);
             
             // 方法1: 尝试直接设置 Cookie(可能因为跨域限制而失败)
             if (cookies.length > 0) {
@@ -218,14 +220,83 @@ function generateRedirectHTML(cookieData, targetHost, targetDomain, requestId =
                 console.log('[浏览器端] 没有 Cookie 需要设置,直接跳转');
             }
             
-            // 对于 Home Assistant 授权流程,直接跳转(不需要 iframe)
-            if (isHomeAssistant) {
-                console.log('[浏览器端] Home Assistant 授权流程,直接跳转到授权端点');
-                console.log('[浏览器端] 授权 URL:', targetUrl);
-                console.log('[浏览器端] 浏览器将处理授权流程并设置 Cookie');
-                console.log('========================================');
-                // 立即跳转,让浏览器处理授权流程
-                window.location.href = targetUrl;
+            // 对于 Home Assistant,在浏览器端执行登录流程
+            if (isHomeAssistant && homeAssistantData) {
+                console.log('[浏览器端] Home Assistant 登录,在浏览器端执行登录流程');
+                console.log('[浏览器端] 目标 URL:', homeAssistantData.targetBaseUrl);
+                console.log('[浏览器端] 用户名:', homeAssistantData.username);
+                
+                // 异步执行登录流程
+                async function loginHomeAssistant() {
+                    try {
+                        console.log('[浏览器端] 步骤1: 创建登录流程...');
+                        const flowResponse = await fetch(homeAssistantData.targetBaseUrl + '/auth/login_flow', {
+                            method: 'POST',
+                            headers: {
+                                'Content-Type': 'application/json'
+                            },
+                            body: JSON.stringify({
+                                client_id: homeAssistantData.targetBaseUrl + '/',
+                                handler: ['homeassistant', null],
+                                redirect_uri: homeAssistantData.targetBaseUrl + '/'
+                            }),
+                            credentials: 'include'
+                        });
+                        
+                        const flowData = await flowResponse.json();
+                        console.log('[浏览器端] 流程创建响应:', flowData);
+                        
+                        if (!flowData.flow_id) {
+                            throw new Error('无法获取 flow_id');
+                        }
+                        
+                        console.log('[浏览器端] 步骤2: 提交用户名和密码...');
+                        const loginResponse = await fetch(homeAssistantData.targetBaseUrl + '/auth/login_flow/' + flowData.flow_id, {
+                            method: 'POST',
+                            headers: {
+                                'Content-Type': 'application/json'
+                            },
+                            body: JSON.stringify({
+                                username: homeAssistantData.username,
+                                password: homeAssistantData.password,
+                                client_id: homeAssistantData.targetBaseUrl + '/'
+                            }),
+                            credentials: 'include'
+                        });
+                        
+                        const loginData = await loginResponse.json();
+                        console.log('[浏览器端] 登录响应:', loginData);
+                        
+                        if (loginData.type === 'create_entry') {
+                            console.log('[浏览器端] 登录成功!准备跳转到授权端点...');
+                            
+                            // 构建授权 URL
+                            const stateData = {
+                                hassUrl: homeAssistantData.targetBaseUrl,
+                                clientId: homeAssistantData.targetBaseUrl + '/'
+                            };
+                            const state = btoa(JSON.stringify(stateData));
+                            const redirectUri = homeAssistantData.targetBaseUrl + '/?auth_callback=1';
+                            const clientId = homeAssistantData.targetBaseUrl + '/';
+                            const authorizeUrl = homeAssistantData.targetBaseUrl + '/auth/authorize?response_type=code&redirect_uri=' + encodeURIComponent(redirectUri) + '&client_id=' + encodeURIComponent(clientId) + '&state=' + encodeURIComponent(state);
+                            
+                            console.log('[浏览器端] 授权 URL:', authorizeUrl);
+                            console.log('[浏览器端] 跳转到授权端点...');
+                            console.log('========================================');
+                            
+                            window.location.href = authorizeUrl;
+                        } else {
+                            throw new Error('登录失败: ' + JSON.stringify(loginData));
+                        }
+                    } catch (error) {
+                        console.error('[浏览器端] 登录失败:', error);
+                        alert('自动登录失败: ' + error.message + '\\n\\n将跳转到登录页面,请手动登录。');
+                        window.location.href = targetUrl;
+                    }
+                }
+                
+                // 执行登录
+                loginHomeAssistant();
                 return;
             }
             
@@ -956,19 +1027,22 @@ app.get('/api/auto-login/:siteId', async (req, res) => {
     });
     
     // 生成跳转 HTML(添加更多调试信息)
-    // 对于 Home Assistant,如果没有 Cookie,直接跳转到授权端点
+    // 对于 Home Assistant,如果没有 Cookie,让浏览器端完成登录
     let redirectUrl = `http://${config.targetHost}/`;
+    let homeAssistantLoginData = null;
+    
     if (config.loginMethod === 'home-assistant' && cookieData.length === 0) {
-      // 构建授权 URL 让浏览器处理
-      const stateData = {
-        hassUrl: config.targetBaseUrl,
-        clientId: `${config.targetBaseUrl}/`
+      console.log(`[${requestId}] Home Assistant 无 Cookie,准备在浏览器端完成登录流程`);
+      // 传递登录信息给浏览器端
+      homeAssistantLoginData = {
+        targetBaseUrl: config.targetBaseUrl,
+        username: credentials.username,
+        password: credentials.password,
+        // 如果后端已获取到 result token,也传递过去
+        resultToken: loginResult.response?.result
       };
-      const state = Buffer.from(JSON.stringify(stateData)).toString('base64');
-      const redirectUri = `${config.targetBaseUrl}/?auth_callback=1`;
-      const clientId = `${config.targetBaseUrl}/`;
-      redirectUrl = `${config.targetBaseUrl}/auth/authorize?response_type=code&redirect_uri=${encodeURIComponent(redirectUri)}&client_id=${encodeURIComponent(clientId)}&state=${encodeURIComponent(state)}`;
-      console.log(`[${requestId}] Home Assistant 无 Cookie,跳转到授权端点: ${redirectUrl}`);
+      redirectUrl = config.targetBaseUrl;
+      console.log(`[${requestId}] 将在浏览器端执行 Home Assistant 登录流程`);
     }
     
     console.log(`[${requestId}] 生成跳转页面,目标: ${redirectUrl}`);
@@ -977,7 +1051,8 @@ app.get('/api/auto-login/:siteId', async (req, res) => {
       config.targetHost,
       config.targetDomain,
       requestId,
-      redirectUrl
+      redirectUrl,
+      homeAssistantLoginData
     );
     
     // 在响应头中设置 Cookie