|
|
@@ -1,33 +1,8 @@
|
|
|
/*
|
|
|
- * Session Auto Login Service - 用于处理URL参数中的session数据并实现自动登录
|
|
|
+ * Session Auto Login Service - 简化的URL参数处理服务
|
|
|
*/
|
|
|
|
|
|
import {logger} from '../logger';
|
|
|
-import sessionStorage from '../sessionStorage';
|
|
|
-import AccountController from '../accounts/accountController';
|
|
|
-import rootScope from '../rootScope';
|
|
|
-
|
|
|
-export interface SessionData {
|
|
|
- account1?: any;
|
|
|
- account2?: any;
|
|
|
- account3?: any;
|
|
|
- account4?: any;
|
|
|
- auth_key_fingerprint?: string;
|
|
|
- user_auth?: any;
|
|
|
- dc?: number;
|
|
|
- // DC认证密钥和服务器盐值
|
|
|
- dc1_auth_key?: any;
|
|
|
- dc1_server_salt?: any;
|
|
|
- dc2_auth_key?: any;
|
|
|
- dc2_server_salt?: any;
|
|
|
- dc3_auth_key?: any;
|
|
|
- dc3_server_salt?: any;
|
|
|
- dc4_auth_key?: any;
|
|
|
- dc4_server_salt?: any;
|
|
|
- dc5_auth_key?: any;
|
|
|
- dc5_server_salt?: any;
|
|
|
- [key: string]: any; // 允许字符串索引
|
|
|
-}
|
|
|
|
|
|
export class SessionAutoLoginService {
|
|
|
private log = logger('[session-auto-login-service]');
|
|
|
@@ -52,252 +27,6 @@ export class SessionAutoLoginService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 解码base64编码的session数据
|
|
|
- */
|
|
|
- public decodeSessionData(encodedData: string): SessionData | null {
|
|
|
- try {
|
|
|
- // 解码base64字符串
|
|
|
- const jsonString = atob(encodedData);
|
|
|
-
|
|
|
- // 解析JSON
|
|
|
- const sessionData: SessionData = JSON.parse(jsonString);
|
|
|
-
|
|
|
- this.log('Successfully decoded session data:', Object.keys(sessionData));
|
|
|
-
|
|
|
- // 调试:检查account1的内容
|
|
|
- if(sessionData.account1) {
|
|
|
- this.log('Account1 keys:', Object.keys(sessionData.account1));
|
|
|
- this.log('Account1 has dc2_auth_key:', !!sessionData.account1.dc2_auth_key);
|
|
|
- }
|
|
|
-
|
|
|
- return sessionData;
|
|
|
- } catch(error) {
|
|
|
- this.log('Error decoding session data:', error);
|
|
|
- return null;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 将session数据保存到localStorage中
|
|
|
- */
|
|
|
- public async saveSessionToStorage(sessionData: SessionData): Promise<boolean> {
|
|
|
- try {
|
|
|
- const storageData: Record<string, any> = {};
|
|
|
-
|
|
|
- // 保存账户数据
|
|
|
- if(sessionData.account1) {
|
|
|
- storageData['account1'] = sessionData.account1;
|
|
|
-
|
|
|
- // 如果account1中包含DC认证密钥,也单独保存
|
|
|
- const account1 = sessionData.account1;
|
|
|
- if(account1.dc1_auth_key) storageData['dc1_auth_key'] = account1.dc1_auth_key;
|
|
|
- if(account1.dc1_server_salt) storageData['dc1_server_salt'] = account1.dc1_server_salt;
|
|
|
- if(account1.dc2_auth_key) storageData['dc2_auth_key'] = account1.dc2_auth_key;
|
|
|
- if(account1.dc2_server_salt) storageData['dc2_server_salt'] = account1.dc2_server_salt;
|
|
|
- if(account1.dc3_auth_key) storageData['dc3_auth_key'] = account1.dc3_auth_key;
|
|
|
- if(account1.dc3_server_salt) storageData['dc3_server_salt'] = account1.dc3_server_salt;
|
|
|
- if(account1.dc4_auth_key) storageData['dc4_auth_key'] = account1.dc4_auth_key;
|
|
|
- if(account1.dc4_server_salt) storageData['dc4_server_salt'] = account1.dc4_server_salt;
|
|
|
- if(account1.dc5_auth_key) storageData['dc5_auth_key'] = account1.dc5_auth_key;
|
|
|
- if(account1.dc5_server_salt) storageData['dc5_server_salt'] = account1.dc5_server_salt;
|
|
|
- }
|
|
|
- if(sessionData.account2) {
|
|
|
- storageData['account2'] = sessionData.account2;
|
|
|
- }
|
|
|
- if(sessionData.account3) {
|
|
|
- storageData['account3'] = sessionData.account3;
|
|
|
- }
|
|
|
- if(sessionData.account4) {
|
|
|
- storageData['account4'] = sessionData.account4;
|
|
|
- }
|
|
|
-
|
|
|
- // 保存其他关键数据
|
|
|
- if(sessionData.auth_key_fingerprint) {
|
|
|
- storageData['auth_key_fingerprint'] = sessionData.auth_key_fingerprint;
|
|
|
- }
|
|
|
- if(sessionData.user_auth) {
|
|
|
- storageData['user_auth'] = sessionData.user_auth;
|
|
|
- }
|
|
|
- if(sessionData.dc) {
|
|
|
- storageData['dc'] = sessionData.dc;
|
|
|
- }
|
|
|
-
|
|
|
- // 保存DC认证密钥和服务器盐值
|
|
|
- const dcKeys = ['dc1_auth_key', 'dc1_server_salt', 'dc2_auth_key', 'dc2_server_salt',
|
|
|
- 'dc3_auth_key', 'dc3_server_salt', 'dc4_auth_key', 'dc4_server_salt',
|
|
|
- 'dc5_auth_key', 'dc5_server_salt'];
|
|
|
-
|
|
|
- for(const key of dcKeys) {
|
|
|
- if(sessionData[key]) {
|
|
|
- storageData[key] = sessionData[key];
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 保存到sessionStorage
|
|
|
- await sessionStorage.set(storageData);
|
|
|
-
|
|
|
- this.log('Successfully saved session data to storage');
|
|
|
- return true;
|
|
|
- } catch(error) {
|
|
|
- this.log('Error saving session data to storage:', error);
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 验证session数据的有效性
|
|
|
- */
|
|
|
- public validateSessionData(sessionData: SessionData): boolean {
|
|
|
- try {
|
|
|
- // 检查是否有有效的账户数据
|
|
|
- const hasValidAccount = sessionData.account1?.userId ||
|
|
|
- sessionData.account2?.userId ||
|
|
|
- sessionData.account3?.userId ||
|
|
|
- sessionData.account4?.userId;
|
|
|
-
|
|
|
- if(!hasValidAccount) {
|
|
|
- this.log('No valid account data found in session');
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- // 检查是否有认证密钥指纹
|
|
|
- if(!sessionData.auth_key_fingerprint) {
|
|
|
- this.log('No auth key fingerprint found in session');
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- // 检查是否有至少一个DC的认证密钥
|
|
|
- const hasAuthKey = sessionData.dc1_auth_key || sessionData.dc2_auth_key ||
|
|
|
- sessionData.dc3_auth_key || sessionData.dc4_auth_key ||
|
|
|
- sessionData.dc5_auth_key;
|
|
|
-
|
|
|
- // 或者检查account1中是否包含认证密钥
|
|
|
- const accountHasAuthKey = sessionData.account1?.dc2_auth_key ||
|
|
|
- sessionData.account1?.dc1_auth_key ||
|
|
|
- sessionData.account1?.dc3_auth_key ||
|
|
|
- sessionData.account1?.dc4_auth_key ||
|
|
|
- sessionData.account1?.dc5_auth_key;
|
|
|
-
|
|
|
- this.log('Has auth key:', hasAuthKey, 'Account has auth key:', accountHasAuthKey);
|
|
|
-
|
|
|
- if(!hasAuthKey && !accountHasAuthKey) {
|
|
|
- this.log('No DC auth key found in session');
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- // 验证认证密钥的格式和长度
|
|
|
- const authKeys = [
|
|
|
- sessionData.dc1_auth_key, sessionData.dc2_auth_key, sessionData.dc3_auth_key,
|
|
|
- sessionData.dc4_auth_key, sessionData.dc5_auth_key,
|
|
|
- sessionData.account1?.dc1_auth_key, sessionData.account1?.dc2_auth_key,
|
|
|
- sessionData.account1?.dc3_auth_key, sessionData.account1?.dc4_auth_key,
|
|
|
- sessionData.account1?.dc5_auth_key
|
|
|
- ].filter(Boolean);
|
|
|
-
|
|
|
- for(const authKey of authKeys) {
|
|
|
- if(typeof authKey === 'string') {
|
|
|
- // 检查认证密钥长度(应该是256字节,即512个十六进制字符)
|
|
|
- if(authKey.length !== 512) {
|
|
|
- this.log('Invalid auth key length:', authKey.length);
|
|
|
- return false;
|
|
|
- }
|
|
|
- // 检查是否为有效的十六进制字符串
|
|
|
- if(!/^[0-9a-fA-F]+$/.test(authKey)) {
|
|
|
- this.log('Invalid auth key format: not hexadecimal');
|
|
|
- return false;
|
|
|
- }
|
|
|
- } else if(authKey instanceof Uint8Array) {
|
|
|
- // 检查Uint8Array长度(应该是256字节)
|
|
|
- if(authKey.length !== 256) {
|
|
|
- this.log('Invalid auth key Uint8Array length:', authKey.length);
|
|
|
- return false;
|
|
|
- }
|
|
|
- } else {
|
|
|
- this.log('Invalid auth key type:', typeof authKey);
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- this.log('Session data validation passed');
|
|
|
- return true;
|
|
|
- } catch(error) {
|
|
|
- this.log('Error validating session data:', error);
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 执行自动登录
|
|
|
- */
|
|
|
- public async performAutoLogin(): Promise<boolean> {
|
|
|
- try {
|
|
|
- // 1. 解析URL参数
|
|
|
- const encodedData = this.parseUrlParams();
|
|
|
- if(!encodedData) {
|
|
|
- this.log('No data parameter found in URL');
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- // 2. 解码session数据
|
|
|
- const sessionData = this.decodeSessionData(encodedData);
|
|
|
- if(!sessionData) {
|
|
|
- this.log('Failed to decode session data');
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- // 3. 验证session数据
|
|
|
- if(!this.validateSessionData(sessionData)) {
|
|
|
- this.log('Session data validation failed');
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- // 4. 保存到localStorage
|
|
|
- const saved = await this.saveSessionToStorage(sessionData);
|
|
|
- if(!saved) {
|
|
|
- this.log('Failed to save session data to storage');
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- // 5. 标记自动登录完成
|
|
|
- this.log('Auto login data saved successfully, system will check authentication state');
|
|
|
-
|
|
|
- return true;
|
|
|
- } catch(error) {
|
|
|
- this.log('Error during auto login:', error);
|
|
|
- // 如果自动登录失败,清除可能已保存的无效数据
|
|
|
- await this.clearInvalidSessionData();
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 清除无效的session数据
|
|
|
- */
|
|
|
- public async clearInvalidSessionData(): Promise<void> {
|
|
|
- try {
|
|
|
- // 清除可能已保存的无效认证密钥
|
|
|
- const keysToClear = [
|
|
|
- 'dc1_auth_key', 'dc1_server_salt',
|
|
|
- 'dc2_auth_key', 'dc2_server_salt',
|
|
|
- 'dc3_auth_key', 'dc3_server_salt',
|
|
|
- 'dc4_auth_key', 'dc4_server_salt',
|
|
|
- 'dc5_auth_key', 'dc5_server_salt',
|
|
|
- 'auth_key_fingerprint', 'user_auth', 'dc'
|
|
|
- ];
|
|
|
-
|
|
|
- const clearData: Record<string, undefined> = {};
|
|
|
- keysToClear.forEach(key => {
|
|
|
- clearData[key] = undefined;
|
|
|
- });
|
|
|
-
|
|
|
- await sessionStorage.set(clearData);
|
|
|
- this.log('Cleared invalid session data');
|
|
|
- } catch(error) {
|
|
|
- this.log('Error clearing invalid session data:', error);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* 清除URL中的data参数
|
|
|
*/
|
|
|
@@ -316,5 +45,5 @@ export class SessionAutoLoginService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// 创建单例实例
|
|
|
+// 导出单例实例
|
|
|
export const sessionAutoLoginService = new SessionAutoLoginService();
|