|
@@ -0,0 +1,135 @@
|
|
|
|
|
+/**
|
|
|
|
|
+ * Home Assistant 前端自动登录工具
|
|
|
|
|
+ * 纯前端实现,无需后端服务器
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Home Assistant OAuth2 自动登录
|
|
|
|
|
+ * @param {string} baseUrl - Home Assistant 基础 URL (例如: http://222.243.138.146:8123)
|
|
|
|
|
+ * @param {string} username - 用户名
|
|
|
|
|
+ * @param {string} password - 密码
|
|
|
|
|
+ * @returns {Promise<boolean>} - 登录是否成功
|
|
|
|
|
+ */
|
|
|
|
|
+export async function autoLoginHomeAssistant(baseUrl, username, password) {
|
|
|
|
|
+ console.log('========================================');
|
|
|
|
|
+ console.log('[前端] Home Assistant 自动登录开始');
|
|
|
|
|
+ console.log('[前端] 目标 URL:', baseUrl);
|
|
|
|
|
+ console.log('[前端] 用户名:', username);
|
|
|
|
|
+ console.log('========================================');
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ // ==========================================
|
|
|
|
|
+ // 步骤1: 创建登录流程
|
|
|
|
|
+ // ==========================================
|
|
|
|
|
+ console.log('[前端] 步骤1: 创建登录流程...');
|
|
|
|
|
+
|
|
|
|
|
+ const flowResponse = await fetch(`${baseUrl}/auth/login_flow`, {
|
|
|
|
|
+ method: 'POST',
|
|
|
|
|
+ headers: {
|
|
|
|
|
+ 'Content-Type': 'application/json',
|
|
|
|
|
+ },
|
|
|
|
|
+ body: JSON.stringify({
|
|
|
|
|
+ client_id: `${baseUrl}/`,
|
|
|
|
|
+ handler: ['homeassistant', null],
|
|
|
|
|
+ redirect_uri: `${baseUrl}/?auth_callback=1`
|
|
|
|
|
+ }),
|
|
|
|
|
+ credentials: 'include', // 包含 Cookie
|
|
|
|
|
+ mode: 'cors' // 允许跨域
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if (!flowResponse.ok) {
|
|
|
|
|
+ throw new Error(`创建登录流程失败: HTTP ${flowResponse.status}`);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const flowData = await flowResponse.json();
|
|
|
|
|
+ console.log('[前端] 流程创建响应:', flowData);
|
|
|
|
|
+
|
|
|
|
|
+ const flowId = flowData.flow_id;
|
|
|
|
|
+ if (!flowId) {
|
|
|
|
|
+ throw new Error('无法获取 flow_id');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ console.log('[前端] 获取到 flow_id:', flowId);
|
|
|
|
|
+
|
|
|
|
|
+ // ==========================================
|
|
|
|
|
+ // 步骤2: 提交用户名和密码
|
|
|
|
|
+ // ==========================================
|
|
|
|
|
+ console.log('[前端] 步骤2: 提交用户名和密码...');
|
|
|
|
|
+
|
|
|
|
|
+ const loginResponse = await fetch(`${baseUrl}/auth/login_flow/${flowId}`, {
|
|
|
|
|
+ method: 'POST',
|
|
|
|
|
+ headers: {
|
|
|
|
|
+ 'Content-Type': 'application/json',
|
|
|
|
|
+ },
|
|
|
|
|
+ body: JSON.stringify({
|
|
|
|
|
+ username: username,
|
|
|
|
|
+ password: password,
|
|
|
|
|
+ client_id: `${baseUrl}/`
|
|
|
|
|
+ }),
|
|
|
|
|
+ credentials: 'include',
|
|
|
|
|
+ mode: 'cors'
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if (!loginResponse.ok) {
|
|
|
|
|
+ throw new Error(`登录失败: HTTP ${loginResponse.status}`);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const loginData = await loginResponse.json();
|
|
|
|
|
+ console.log('[前端] 登录响应:', loginData);
|
|
|
|
|
+
|
|
|
|
|
+ // ==========================================
|
|
|
|
|
+ // 步骤3: 处理 Authorization Code
|
|
|
|
|
+ // ==========================================
|
|
|
|
|
+ if (loginData.result && loginData.type === 'create_entry') {
|
|
|
|
|
+ const authCode = loginData.result;
|
|
|
|
|
+ console.log('[前端] 登录成功!获取到 Authorization Code:', authCode);
|
|
|
|
|
+
|
|
|
|
|
+ // 构造重定向 URL
|
|
|
|
|
+ const redirectUrl = `${baseUrl}/?auth_callback=1&code=${encodeURIComponent(authCode)}`;
|
|
|
|
|
+
|
|
|
|
|
+ console.log('[前端] 准备跳转到:', redirectUrl);
|
|
|
|
|
+ console.log('[前端] Home Assistant 前端将自动完成 Token 交换');
|
|
|
|
|
+ console.log('========================================');
|
|
|
|
|
+
|
|
|
|
|
+ // 跳转到 Home Assistant,完成登录
|
|
|
|
|
+ window.location.href = redirectUrl;
|
|
|
|
|
+ return true;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ throw new Error('登录失败: 未返回 Authorization Code');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('[前端] 自动登录失败:', error);
|
|
|
|
|
+ console.error('[前端] 错误详情:', error.message);
|
|
|
|
|
+
|
|
|
|
|
+ // 如果是 CORS 错误,提供解决方案提示
|
|
|
|
|
+ if (error.message.includes('CORS') || error.message.includes('fetch')) {
|
|
|
|
|
+ console.error('[前端] ⚠️ 检测到 CORS 跨域错误!');
|
|
|
|
|
+ console.error('[前端] 解决方案:');
|
|
|
|
|
+ console.error('[前端] 1. 配置 Home Assistant 允许跨域请求');
|
|
|
|
|
+ console.error('[前端] 2. 使用 Trusted Networks(推荐)');
|
|
|
|
|
+ console.error('[前端] 3. 使用后端代理服务');
|
|
|
|
|
+
|
|
|
|
|
+ alert(
|
|
|
|
|
+ '自动登录失败:跨域限制\n\n' +
|
|
|
|
|
+ '由于浏览器安全策略,无法直接访问 Home Assistant API。\n\n' +
|
|
|
|
|
+ '建议使用 Trusted Networks 配置实现自动登录。\n\n' +
|
|
|
|
|
+ '是否跳转到 Home Assistant 登录页面?'
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ console.log('========================================');
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 简化版:直接跳转(利用 Trusted Networks)
|
|
|
|
|
+ * @param {string} baseUrl - Home Assistant 基础 URL
|
|
|
|
|
+ */
|
|
|
|
|
+export function directJumpHomeAssistant(baseUrl) {
|
|
|
|
|
+ console.log('[前端] 直接跳转到 Home Assistant:', baseUrl);
|
|
|
|
|
+ console.log('[前端] 如果已配置 Trusted Networks,将自动登录');
|
|
|
|
|
+ window.location.href = baseUrl;
|
|
|
|
|
+}
|
|
|
|
|
+
|