custom-login-script.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. const axios = require('axios');
  2. const CryptoJS = require('crypto-js');
  3. const NodeRSA = require('node-rsa');
  4. // 配置信息
  5. const CONFIG = {
  6. BASE_URL: 'http://localhost/dev-api',
  7. LOGIN_ENDPOINT: '/auth/login',
  8. CLIENT_ID: 'e5cd7e4891bf95d1d19206ce24a7b32e',
  9. TENANT_ID: '000000',
  10. REFERER: 'http://localhost/login?redirect=%252Findex',
  11. // RSA公钥
  12. RSA_PUBLIC_KEY:
  13. 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==',
  14. };
  15. // 默认登录凭据
  16. const CREDENTIALS = {
  17. username: 'admin',
  18. password: 'admin123',
  19. };
  20. /**
  21. * 生成随机AES密钥
  22. */
  23. function generateRandomAESKey(length = 32) {
  24. const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  25. let result = '';
  26. for (let i = 0; i < length; i++) {
  27. result += characters.charAt(Math.floor(Math.random() * characters.length));
  28. }
  29. return result;
  30. }
  31. /**
  32. * AES加密数据
  33. */
  34. function encryptWithAES(data, key) {
  35. const keyUtf8 = CryptoJS.enc.Utf8.parse(key);
  36. const encrypted = CryptoJS.AES.encrypt(data, keyUtf8, {
  37. mode: CryptoJS.mode.ECB,
  38. padding: CryptoJS.pad.Pkcs7,
  39. });
  40. return encrypted.toString();
  41. }
  42. /**
  43. * RSA加密AES密钥
  44. */
  45. function encryptAESKeyWithRSA(aesKey) {
  46. try {
  47. const pemKey = `-----BEGIN PUBLIC KEY-----\n${CONFIG.RSA_PUBLIC_KEY}\n-----END PUBLIC KEY-----`;
  48. const rsaKey = new NodeRSA(pemKey);
  49. rsaKey.setOptions({ encryptionScheme: 'pkcs1' });
  50. // 将AES密钥转为Base64
  51. const aesKeyBase64 = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(aesKey));
  52. // RSA加密
  53. return rsaKey.encrypt(aesKeyBase64, 'base64');
  54. } catch (error) {
  55. console.error('RSA加密失败:', error.message);
  56. return null;
  57. }
  58. }
  59. /**
  60. * 自定义Header登录 - 按照用户要求
  61. */
  62. async function customHeaderLogin(credentials = CREDENTIALS) {
  63. console.log('🔐 开始自定义Header登录...');
  64. console.log('📍 接口地址:', CONFIG.BASE_URL + CONFIG.LOGIN_ENDPOINT);
  65. try {
  66. // 1. 生成AES密钥
  67. const aesKey = generateRandomAESKey(32);
  68. console.log('🔑 生成AES密钥:', aesKey);
  69. // 2. 准备登录数据
  70. const loginData = {
  71. tenantId: CONFIG.TENANT_ID,
  72. username: credentials.username,
  73. password: credentials.password,
  74. clientId: CONFIG.CLIENT_ID,
  75. grantType: 'password',
  76. };
  77. console.log('📋 登录数据:', JSON.stringify(loginData, null, 2));
  78. // 3. AES加密登录数据
  79. const encryptedData = encryptWithAES(JSON.stringify(loginData), aesKey);
  80. console.log('🔐 AES加密后数据长度:', encryptedData.length);
  81. // 4. RSA加密AES密钥
  82. const encryptedKey = encryptAESKeyWithRSA(aesKey);
  83. if (!encryptedKey) {
  84. throw new Error('RSA加密AES密钥失败');
  85. }
  86. console.log('🔑 RSA加密后密钥长度:', encryptedKey.length);
  87. // 5. 按照用户要求设置Header
  88. const headers = {
  89. 'Content-Type': 'application/json;charset=utf-8',
  90. clientid: CONFIG.CLIENT_ID, // 用户要求的clientid
  91. 'encrypt-key': encryptedKey, // 用户要求的encrypt-key
  92. referer: CONFIG.REFERER, // 用户要求的referer
  93. 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
  94. isToken: 'false',
  95. isEncrypt: 'true',
  96. repeatSubmit: 'false',
  97. };
  98. console.log('📤 请求头设置:');
  99. console.log(' - clientid:', headers.clientid);
  100. console.log(' - encrypt-key:', encryptedKey.substring(0, 50) + '...');
  101. console.log(' - referer:', headers.referer);
  102. console.log(' - Content-Type:', headers['Content-Type']);
  103. // 6. 发送登录请求
  104. console.log('\n🚀 发送登录请求...');
  105. const response = await axios.post(CONFIG.BASE_URL + CONFIG.LOGIN_ENDPOINT, encryptedData, {
  106. headers: headers,
  107. timeout: 10000,
  108. });
  109. // 7. 处理响应
  110. console.log('✅ 请求成功!');
  111. console.log('📊 响应状态:', response.status);
  112. console.log('📄 响应数据:', JSON.stringify(response.data, null, 2));
  113. // 8. 提取Token
  114. if (response.data.code === 200 && response.data.data?.access_token) {
  115. const token = response.data.data.access_token;
  116. console.log('\n🎯 成功获取Token!');
  117. console.log('🎫 Token:', token);
  118. console.log('🎫 Token长度:', token.length);
  119. console.log('🎫 Token前50字符:', token.substring(0, 50) + '...');
  120. // 测试Token有效性
  121. await testTokenValidity(token);
  122. return {
  123. success: true,
  124. token: token,
  125. data: response.data,
  126. };
  127. } else {
  128. console.log('⚠️ 登录请求成功,但未获取到Token');
  129. console.log('❌ 错误信息:', response.data.msg);
  130. return {
  131. success: false,
  132. error: response.data.msg || 'Unknown error',
  133. data: response.data,
  134. };
  135. }
  136. } catch (error) {
  137. console.log('❌ 登录失败!');
  138. if (error.response) {
  139. console.log('📊 错误状态码:', error.response.status);
  140. console.log('📄 错误响应:', JSON.stringify(error.response.data, null, 2));
  141. // 特殊错误处理
  142. if (error.response.status === 500) {
  143. console.log('💡 提示: 这可能是服务器端加密处理问题');
  144. } else if (error.response.status === 403) {
  145. console.log('💡 提示: 这是权限配置问题,需要联系管理员');
  146. }
  147. } else if (error.request) {
  148. console.log('🌐 网络错误,请检查服务器是否启动');
  149. console.log('📡 请求详情:', error.message);
  150. } else {
  151. console.log('⚙️ 请求配置错误:', error.message);
  152. }
  153. return {
  154. success: false,
  155. error: error.response?.data || error.message,
  156. };
  157. }
  158. }
  159. /**
  160. * 测试Token有效性
  161. */
  162. async function testTokenValidity(token) {
  163. console.log('\n🧪 测试Token有效性...');
  164. try {
  165. const response = await axios.get(CONFIG.BASE_URL + '/system/user/getInfo', {
  166. headers: {
  167. Authorization: `Bearer ${token}`,
  168. clientid: CONFIG.CLIENT_ID,
  169. referer: CONFIG.REFERER,
  170. 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
  171. },
  172. timeout: 10000,
  173. });
  174. console.log('✅ Token有效! 用户信息获取成功');
  175. console.log('👤 用户信息:', JSON.stringify(response.data, null, 2));
  176. return true;
  177. } catch (error) {
  178. console.log('❌ Token测试失败');
  179. if (error.response) {
  180. console.log('📊 错误状态码:', error.response.status);
  181. console.log('📄 错误信息:', error.response.data);
  182. } else {
  183. console.log('🌐 网络错误:', error.message);
  184. }
  185. return false;
  186. }
  187. }
  188. /**
  189. * 标准非加密登录 (备用方案)
  190. */
  191. async function standardLogin(credentials = CREDENTIALS) {
  192. console.log('\n🔓 尝试标准非加密登录 (备用方案)...');
  193. const loginData = {
  194. tenantId: CONFIG.TENANT_ID,
  195. username: credentials.username,
  196. password: credentials.password,
  197. clientId: CONFIG.CLIENT_ID,
  198. grantType: 'password',
  199. };
  200. const headers = {
  201. 'Content-Type': 'application/json;charset=utf-8',
  202. clientid: CONFIG.CLIENT_ID,
  203. referer: CONFIG.REFERER,
  204. 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
  205. };
  206. try {
  207. const response = await axios.post(CONFIG.BASE_URL + CONFIG.LOGIN_ENDPOINT, loginData, {
  208. headers,
  209. timeout: 10000,
  210. });
  211. console.log('✅ 标准登录请求成功');
  212. console.log('📄 响应数据:', JSON.stringify(response.data, null, 2));
  213. if (response.data.code === 200 && response.data.data?.access_token) {
  214. const token = response.data.data.access_token;
  215. console.log('🎫 获取到Token:', token.substring(0, 50) + '...');
  216. return { success: true, token: token, data: response.data };
  217. } else {
  218. return { success: false, error: response.data.msg, data: response.data };
  219. }
  220. } catch (error) {
  221. console.log('❌ 标准登录失败');
  222. if (error.response) {
  223. console.log('📊 状态码:', error.response.status);
  224. console.log('📄 错误信息:', error.response.data);
  225. }
  226. return { success: false, error: error.response?.data || error.message };
  227. }
  228. }
  229. /**
  230. * 主函数 - 智能登录策略
  231. */
  232. async function smartLogin(credentials) {
  233. console.log('🌟'.repeat(25));
  234. console.log('🚀 智能登录脚本 - 自定义Header版本');
  235. console.log('🌟'.repeat(25));
  236. let result = null;
  237. // 策略1: 首先尝试加密登录
  238. console.log('\n📋 策略1: 尝试加密登录 (用户指定Header格式)');
  239. result = await customHeaderLogin(credentials);
  240. if (result.success) {
  241. console.log('\n🎉 加密登录成功!');
  242. return result;
  243. }
  244. // 策略2: 如果加密登录失败,尝试标准登录
  245. console.log('\n📋 策略2: 尝试标准非加密登录 (备用方案)');
  246. result = await standardLogin(credentials);
  247. if (result.success) {
  248. console.log('\n🎉 标准登录成功!');
  249. return result;
  250. }
  251. // 所有策略都失败
  252. console.log('\n❌ 所有登录策略都失败了');
  253. console.log('🔧 建议检查:');
  254. console.log(' 1. 服务器是否正常运行');
  255. console.log(' 2. 用户权限是否正确配置');
  256. console.log(' 3. 网络连接是否正常');
  257. return result;
  258. }
  259. // 导出函数
  260. module.exports = {
  261. customHeaderLogin,
  262. standardLogin,
  263. testTokenValidity,
  264. smartLogin,
  265. CONFIG,
  266. CREDENTIALS,
  267. };
  268. // 直接运行脚本
  269. if (require.main === module) {
  270. console.log('🔥 检查依赖包...');
  271. // 检查依赖
  272. try {
  273. require('axios');
  274. require('crypto-js');
  275. require('node-rsa');
  276. console.log('✅ 所有依赖包检查完成');
  277. } catch (error) {
  278. console.error('❌ 缺少依赖包,请运行: npm install axios crypto-js node-rsa');
  279. process.exit(1);
  280. }
  281. // 运行智能登录
  282. smartLogin(CREDENTIALS)
  283. .then((result) => {
  284. console.log('\n' + '🌟'.repeat(25));
  285. console.log('📊 最终结果:');
  286. if (result.success) {
  287. console.log('✅ 登录成功!');
  288. console.log('🎫 Token:', result.token);
  289. console.log('💡 您可以使用这个Token进行后续API调用');
  290. } else {
  291. console.log('❌ 登录失败!');
  292. console.log('📄 错误信息:', result.error);
  293. }
  294. console.log('🌟'.repeat(25));
  295. })
  296. .catch((error) => {
  297. console.error('💥 脚本运行出错:', error.message);
  298. process.exit(1);
  299. });
  300. }