Complete integration of the old clinical research platform (www.xunzhengyixue.com) into the new AI platform via Token injection + iframe embedding: Backend: - Add legacy-bridge module (MySQL pool, auth service, routes) - POST /api/v1/legacy/auth: JWT -> phone lookup -> Token injection into old MySQL - Auto-create user in old system if not found (matched by phone number) Frontend: - LegacySystemPage: iframe container with Bridge URL construction - ResearchManagement + StatisticalTools entry components - Module registry updated from external links to iframe embed mode ECS (token-bridge.html deployed to www.xunzhengyixue.com): - Wrapper Bridge: sets cookies within same-origin context - Storage Access API for cross-site dev environments - CSS injection: hide old system nav/footer, remove padding gaps - Inner iframe loads target page with full DOM access (same-origin) Key technical decisions: - Token injection (direct MySQL write) instead of calling login API - Wrapper Bridge instead of parent-page cookie setting (cross-origin fix) - Storage Access API + SameSite=None;Secure for third-party cookie handling - User isolation guaranteed by phone number matching Documentation: - Integration plan v4.0 with full implementation record - Implementation summary with 6 pitfalls documented - System status guide updated (ST module now integrated) Tested: Local E2E verified - auto login, research management, 126 statistical tools, report generation, download, UI layout all working correctly Made-with: Cursor
121 lines
4.3 KiB
TypeScript
121 lines
4.3 KiB
TypeScript
/**
|
|
* Legacy Auth Token Injection Test
|
|
*
|
|
* Tests the full flow:
|
|
* 1. Connect to old system MySQL (xzyx_online)
|
|
* 2. Find user by phone
|
|
* 3. Generate MD5 token (same formula as old Java system)
|
|
* 4. Insert token into u_user_token
|
|
* 5. Print cookie-setting instructions for manual browser verification
|
|
*
|
|
* Usage:
|
|
* npx tsx scripts/test-legacy-auth.ts <phone>
|
|
* npx tsx scripts/test-legacy-auth.ts 18611348738
|
|
*/
|
|
|
|
import mysql from 'mysql2/promise';
|
|
import crypto from 'crypto';
|
|
|
|
const MYSQL_CONFIG = {
|
|
host: process.env.LEGACY_MYSQL_HOST || '8.154.22.149',
|
|
port: parseInt(process.env.LEGACY_MYSQL_PORT || '3306'),
|
|
user: process.env.LEGACY_MYSQL_USER || 'xzyx_rw',
|
|
password: process.env.LEGACY_MYSQL_PASSWORD || 'SKJfdwalkd',
|
|
database: process.env.LEGACY_MYSQL_DATABASE || 'xzyx_online',
|
|
};
|
|
|
|
function generateToken(userId: number): string {
|
|
const timestamp = Date.now();
|
|
const raw = `KyKz1.0:${userId}:${timestamp}`;
|
|
return crypto.createHash('md5').update(raw).digest('hex');
|
|
}
|
|
|
|
async function main() {
|
|
const phone = process.argv[2];
|
|
if (!phone) {
|
|
console.error('Usage: npx tsx scripts/test-legacy-auth.ts <phone>');
|
|
console.error('Example: npx tsx scripts/test-legacy-auth.ts 18611348738');
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log('='.repeat(60));
|
|
console.log('Legacy Auth Token Injection Test');
|
|
console.log('='.repeat(60));
|
|
|
|
// Step 1: Connect
|
|
console.log('\n[1/5] Connecting to MySQL...');
|
|
const conn = await mysql.createConnection(MYSQL_CONFIG);
|
|
console.log(` OK - connected to ${MYSQL_CONFIG.host}:${MYSQL_CONFIG.port}/${MYSQL_CONFIG.database}`);
|
|
|
|
// Step 2: Find user
|
|
console.log(`\n[2/5] Looking up user by phone: ${phone}`);
|
|
const [rows] = await conn.execute<any[]>(
|
|
'SELECT id, phone, nickname, real_name, user_role FROM u_user_info WHERE phone = ?',
|
|
[phone],
|
|
);
|
|
|
|
if (rows.length === 0) {
|
|
console.log(' User NOT found. To test, pick an existing user:');
|
|
const [sample] = await conn.execute<any[]>(
|
|
'SELECT id, phone, nickname, real_name FROM u_user_info LIMIT 5',
|
|
);
|
|
console.table(sample);
|
|
await conn.end();
|
|
process.exit(1);
|
|
}
|
|
|
|
const user = rows[0];
|
|
console.log(` Found: id=${user.id}, nickname="${user.nickname}", role=${user.user_role}`);
|
|
|
|
// Step 3: Generate token
|
|
console.log('\n[3/5] Generating MD5 token...');
|
|
const token = generateToken(user.id);
|
|
console.log(` Token: ${token}`);
|
|
|
|
// Step 4: Delete old tokens + insert new one
|
|
// gen_time must be milliseconds since epoch (Java System.currentTimeMillis()),
|
|
// NOT MySQL NOW(). The old system's isTimeout() does millisecond arithmetic.
|
|
console.log('\n[4/5] Deleting old tokens and inserting new one...');
|
|
await conn.execute('DELETE FROM u_user_token WHERE user_id = ?', [user.id]);
|
|
const genTime = Date.now();
|
|
await conn.execute(
|
|
'INSERT INTO u_user_token (user_id, token, gen_time, user_role) VALUES (?, ?, ?, ?)',
|
|
[user.id, token, genTime, user.user_role],
|
|
);
|
|
console.log(` OK - token inserted (gen_time=${genTime}, which is ${new Date(genTime).toISOString()})`);
|
|
|
|
// Step 5: Verify
|
|
console.log('\n[5/5] Verifying token in database...');
|
|
const [verify] = await conn.execute<any[]>(
|
|
'SELECT id, user_id, token, gen_time, user_role FROM u_user_token WHERE token = ?',
|
|
[token],
|
|
);
|
|
console.log(' Verified:');
|
|
console.table(verify);
|
|
|
|
await conn.end();
|
|
|
|
// Print manual test instructions
|
|
console.log('\n' + '='.repeat(60));
|
|
console.log('TOKEN INJECTION SUCCESSFUL!');
|
|
console.log('='.repeat(60));
|
|
console.log('\nManual browser test:');
|
|
console.log('1. Open browser, go to https://www.xunzhengyixue.com');
|
|
console.log('2. Open DevTools (F12) -> Console');
|
|
console.log('3. Paste the following 3 lines:\n');
|
|
|
|
const nickname = user.nickname || user.real_name || phone;
|
|
console.log(`document.cookie = "token=${token}; domain=.xunzhengyixue.com; path=/";`);
|
|
console.log(`document.cookie = "nickname=${encodeURIComponent(nickname)}; domain=.xunzhengyixue.com; path=/";`);
|
|
console.log(`document.cookie = "id=${user.id}; domain=.xunzhengyixue.com; path=/";`);
|
|
|
|
console.log('\n4. Refresh the page (F5)');
|
|
console.log('5. You should see the user\'s projects without logging in manually');
|
|
console.log('\n' + '='.repeat(60));
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error('Test failed:', err);
|
|
process.exit(1);
|
|
});
|