const axios = require('axios'); // 测试重定向URI匹配逻辑 function testRedirectUriMatching() { console.log('🧪 测试重定向URI匹配逻辑...\n'); // 模拟数据库中存储的URI const storedUris = [ 'http://localhost:3001/third-party-app.html', 'http://localhost:3001/callback', 'https://example.com/callback' ]; // 测试用例 const testCases = [ { requested: 'http://127.0.0.1:5500/public/third-party-app.html', expected: true, description: '不同主机名和端口,相同路径' }, { requested: 'http://localhost:3001/third-party-app.html', expected: true, description: '完全匹配' }, { requested: 'http://localhost:3001/callback', expected: true, description: '匹配callback路径' }, { requested: 'http://127.0.0.1:8080/callback', expected: true, description: '不同端口,相同路径' }, { requested: 'http://localhost:3001/different-path.html', expected: false, description: '路径不匹配' }, { requested: 'https://localhost:3001/third-party-app.html', expected: false, description: '协议不匹配' } ]; // 验证函数(与后端逻辑相同) const isValidRedirectUri = (storedUris, requestedUri) => { try { const requestedUrl = new URL(requestedUri); for (const storedUri of storedUris) { const storedUrl = new URL(storedUri); // 检查协议是否匹配 if (requestedUrl.protocol !== storedUrl.protocol) { continue; } // 获取文件名(路径的最后一部分) const requestedFilename = requestedUrl.pathname.split('/').pop(); const storedFilename = storedUrl.pathname.split('/').pop(); // 检查文件名是否匹配,忽略路径前缀 if (requestedFilename === storedFilename) { return true; } // 如果文件名不匹配,检查完整路径是否匹配 if (requestedUrl.pathname === storedUrl.pathname) { return true; } } return false; } catch (error) { return false; } }; // 运行测试 let passed = 0; let total = testCases.length; testCases.forEach((testCase, index) => { const result = isValidRedirectUri(storedUris, testCase.requested); const status = result === testCase.expected ? '✅' : '❌'; console.log(`${status} 测试 ${index + 1}: ${testCase.description}`); console.log(` 请求URI: ${testCase.requested}`); console.log(` 期望结果: ${testCase.expected}, 实际结果: ${result}`); console.log(''); if (result === testCase.expected) { passed++; } }); console.log(`📊 测试结果: ${passed}/${total} 通过`); if (passed === total) { console.log('🎉 所有测试通过!重定向URI验证逻辑正常工作。'); } else { console.log('⚠️ 部分测试失败,需要检查逻辑。'); } } // 测试实际的OAuth流程 async function testOAuthFlow() { console.log('\n🚀 测试实际OAuth流程...\n'); try { // 1. 注册用户 const testUser = { username: `testuser_${Date.now()}`, email: `testuser_${Date.now()}@example.com`, password: 'TestPassword123' }; console.log('1. 注册测试用户...'); const registerResponse = await axios.post('http://localhost:3000/api/auth/register', testUser); if (!registerResponse.data.success) { console.log('❌ 用户注册失败:', registerResponse.data.message); return; } console.log('✅ 用户注册成功'); // 2. 用户登录 console.log('\n2. 用户登录...'); const loginResponse = await axios.post('http://localhost:3000/api/auth/login', { username: testUser.username, password: testUser.password }); if (!loginResponse.data.success) { console.log('❌ 用户登录失败:', loginResponse.data.message); return; } const userToken = loginResponse.data.data.token; console.log('✅ 用户登录成功'); // 3. 创建OAuth客户端 console.log('\n3. 创建OAuth客户端...'); const clientData = { name: '测试应用', description: '测试重定向URI匹配', redirect_uris: ['http://localhost:3001/third-party-app.html'] }; const clientResponse = await axios.post('http://localhost:3000/api/oauth/clients', clientData, { headers: { 'Authorization': `Bearer ${userToken}` } }); if (!clientResponse.data.success) { console.log('❌ OAuth客户端创建失败:', clientResponse.data.message); return; } const clientId = clientResponse.data.data.client_id; console.log('✅ OAuth客户端创建成功'); console.log(` 客户端ID: ${clientId}`); // 4. 测试授权请求 console.log('\n4. 测试授权请求...'); const authParams = new URLSearchParams({ response_type: 'code', client_id: clientId, redirect_uri: 'http://127.0.0.1:5500/public/third-party-app.html', scope: 'read write', state: 'test123' }); const authResponse = await axios.get(`http://localhost:3000/api/oauth/authorize?${authParams}`, { headers: { 'Authorization': `Bearer ${userToken}` } }); if (authResponse.data.success) { console.log('✅ 授权请求成功!'); console.log(` 应用名称: ${authResponse.data.data.client.name}`); console.log(` 请求权限: ${authResponse.data.data.scopes.join(', ')}`); } else { console.log('❌ 授权请求失败:', authResponse.data.message); if (authResponse.data.debug) { console.log(' 调试信息:', authResponse.data.debug); } } } catch (error) { console.error('❌ 测试过程中发生错误:', error.response?.data || error.message); } } // 运行测试 if (require.main === module) { testRedirectUriMatching(); testOAuthFlow(); } module.exports = { testRedirectUriMatching, testOAuthFlow };