|
|
@@ -226,23 +226,27 @@ function generateRedirectHTML(cookieData, targetHost, targetDomain, requestId =
|
|
|
console.log('[浏览器端] 目标 URL:', homeAssistantData.targetBaseUrl);
|
|
|
console.log('[浏览器端] 用户名:', homeAssistantData.username);
|
|
|
|
|
|
- // 异步执行登录流程
|
|
|
+ // 异步执行登录流程(通过后端代理避免 CORS)
|
|
|
async function loginHomeAssistant() {
|
|
|
try {
|
|
|
- console.log('[浏览器端] 步骤1: 创建登录流程...');
|
|
|
- const flowResponse = await fetch(homeAssistantData.targetBaseUrl + '/auth/login_flow', {
|
|
|
+ console.log('[浏览器端] 步骤1: 创建登录流程(通过代理)...');
|
|
|
+ // 使用后端代理避免 CORS 问题
|
|
|
+ const proxyBaseUrl = window.location.origin; // 后端服务器地址
|
|
|
+
|
|
|
+ const flowResponse = await fetch(proxyBaseUrl + '/api/home-assistant-proxy/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'
|
|
|
+ targetBaseUrl: homeAssistantData.targetBaseUrl
|
|
|
+ })
|
|
|
});
|
|
|
|
|
|
+ if (!flowResponse.ok) {
|
|
|
+ throw new Error('创建登录流程失败: ' + flowResponse.status);
|
|
|
+ }
|
|
|
+
|
|
|
const flowData = await flowResponse.json();
|
|
|
console.log('[浏览器端] 流程创建响应:', flowData);
|
|
|
|
|
|
@@ -250,20 +254,24 @@ function generateRedirectHTML(cookieData, targetHost, targetDomain, requestId =
|
|
|
throw new Error('无法获取 flow_id');
|
|
|
}
|
|
|
|
|
|
- console.log('[浏览器端] 步骤2: 提交用户名和密码...');
|
|
|
- const loginResponse = await fetch(homeAssistantData.targetBaseUrl + '/auth/login_flow/' + flowData.flow_id, {
|
|
|
+ console.log('[浏览器端] 步骤2: 提交用户名和密码(通过代理)...');
|
|
|
+ const loginResponse = await fetch(proxyBaseUrl + '/api/home-assistant-proxy/login', {
|
|
|
method: 'POST',
|
|
|
headers: {
|
|
|
'Content-Type': 'application/json'
|
|
|
},
|
|
|
body: JSON.stringify({
|
|
|
+ targetBaseUrl: homeAssistantData.targetBaseUrl,
|
|
|
+ flowId: flowData.flow_id,
|
|
|
username: homeAssistantData.username,
|
|
|
- password: homeAssistantData.password,
|
|
|
- client_id: homeAssistantData.targetBaseUrl + '/'
|
|
|
- }),
|
|
|
- credentials: 'include'
|
|
|
+ password: homeAssistantData.password
|
|
|
+ })
|
|
|
});
|
|
|
|
|
|
+ if (!loginResponse.ok) {
|
|
|
+ throw new Error('登录失败: ' + loginResponse.status);
|
|
|
+ }
|
|
|
+
|
|
|
const loginData = await loginResponse.json();
|
|
|
console.log('[浏览器端] 登录响应:', loginData);
|
|
|
|
|
|
@@ -1096,6 +1104,59 @@ app.get('/api/auto-login/:siteId', async (req, res) => {
|
|
|
}
|
|
|
});
|
|
|
|
|
|
+// Home Assistant 登录代理端点(解决浏览器 CORS 问题)
|
|
|
+app.post('/api/home-assistant-proxy/login-flow', async (req, res) => {
|
|
|
+ try {
|
|
|
+ const targetBaseUrl = req.body.targetBaseUrl;
|
|
|
+ console.log('[代理] 创建 Home Assistant 登录流程:', targetBaseUrl);
|
|
|
+
|
|
|
+ const response = await axios.post(
|
|
|
+ `${targetBaseUrl}/auth/login_flow`,
|
|
|
+ {
|
|
|
+ client_id: `${targetBaseUrl}/`,
|
|
|
+ handler: ['homeassistant', null],
|
|
|
+ redirect_uri: `${targetBaseUrl}/`
|
|
|
+ },
|
|
|
+ {
|
|
|
+ headers: {
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ res.json(response.data);
|
|
|
+ } catch (error) {
|
|
|
+ console.error('[代理] 创建登录流程失败:', error.message);
|
|
|
+ res.status(500).json({ error: error.message });
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+app.post('/api/home-assistant-proxy/login', async (req, res) => {
|
|
|
+ try {
|
|
|
+ const { targetBaseUrl, flowId, username, password } = req.body;
|
|
|
+ console.log('[代理] 提交 Home Assistant 登录凭据:', targetBaseUrl, flowId);
|
|
|
+
|
|
|
+ const response = await axios.post(
|
|
|
+ `${targetBaseUrl}/auth/login_flow/${flowId}`,
|
|
|
+ {
|
|
|
+ username: username,
|
|
|
+ password: password,
|
|
|
+ client_id: `${targetBaseUrl}/`
|
|
|
+ },
|
|
|
+ {
|
|
|
+ headers: {
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ res.json(response.data);
|
|
|
+ } catch (error) {
|
|
|
+ console.error('[代理] 登录失败:', error.message);
|
|
|
+ res.status(500).json({ error: error.message });
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
// 获取所有配置的网站列表
|
|
|
app.get('/api/auto-login', (req, res) => {
|
|
|
const sites = Object.keys(autoLoginConfig).map(siteId => ({
|