GetLoginUrl.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. const API = require("../../../lib/API")
  2. const axios = require('axios')
  3. const { BaseStdResponse } = require("../../../BaseStdResponse");
  4. const https = require("https")
  5. const { normalizeSocialType } = require('../../../lib/UniLoginClient')
  6. const { getRuntimeConfig } = require('../../../lib/RuntimeConfig')
  7. class GetLoginUrl extends API {
  8. constructor() {
  9. super();
  10. this.setPath('/UniLogin/GetLoginUrl')
  11. this.setMethod('GET')
  12. }
  13. async onRequest(req, res) {
  14. let { type, device, action, from, mode } = req.query
  15. type = normalizeSocialType(type)
  16. if (!type)
  17. return res.json({
  18. ...BaseStdResponse.ERR,
  19. msg: '不支持的第三方登录类型'
  20. })
  21. const uniConfig = await getRuntimeConfig('unilogin', { required: false, defaultValue: null })
  22. if (!uniConfig || !uniConfig.url || !uniConfig.appid || !uniConfig.appkey) {
  23. return res.json({
  24. ...BaseStdResponse.ERR,
  25. msg: '聚合登录暂未配置,请使用账号密码登录'
  26. })
  27. }
  28. /** 解析 URL 与 hash 内查询串,判断 query 是否已包含某键(避免对整段 URL 做子串误判) */
  29. const redirectUrlHasQueryKey = (redirectUrl, key) => {
  30. if (!redirectUrl || !key) return false
  31. try {
  32. const u = new URL(redirectUrl)
  33. if (u.searchParams.has(key)) return true
  34. const h = u.hash || ''
  35. const qPos = h.indexOf('?')
  36. if (qPos === -1) return false
  37. return new URLSearchParams(h.slice(qPos + 1)).has(key)
  38. } catch {
  39. return false
  40. }
  41. }
  42. const appendQuery = (redirectUrl) => {
  43. const params = []
  44. if (mode && !redirectUrlHasQueryKey(redirectUrl, 'mode'))
  45. params.push(`mode=${encodeURIComponent(mode)}`)
  46. if (action && !redirectUrlHasQueryKey(redirectUrl, 'action'))
  47. params.push(`action=${encodeURIComponent(action)}`)
  48. if (from && !redirectUrlHasQueryKey(redirectUrl, 'from'))
  49. params.push(`from=${encodeURIComponent(from)}`)
  50. if (params.length === 0)
  51. return redirectUrl
  52. return `${redirectUrl}${redirectUrl.includes('?') ? '&' : '?'}${params.join('&')}`
  53. }
  54. let redirectUri = appendQuery(uniConfig.return_url)
  55. let url = `${uniConfig.url}/connect.php?act=login&appid=${uniConfig.appid}&appkey=${uniConfig.appkey}&type=${type}&redirect_uri=${encodeURIComponent(redirectUri)}`
  56. if (device && device === 'uniapp')
  57. url = `${uniConfig.url}/connect.php?act=login&appid=${uniConfig.appid}&appkey=${uniConfig.appkey}&type=${type}&redirect_uri=${encodeURIComponent(appendQuery(uniConfig.uni_return_url))}`
  58. try {
  59. const r = await axios.get(url, {
  60. proxy: false,
  61. httpsAgent: new https.Agent({
  62. rejectUnauthorized: false
  63. })
  64. })
  65. if (!r || r.data?.code !== 0 || !r.data?.url) {
  66. this.logger.error(`获取聚合登录链接失败!${r.data?.msg || 'api接口错误'}`)
  67. return res.json({
  68. ...BaseStdResponse.ERR,
  69. msg: '请尝试其他登录方式或稍后再试'
  70. })
  71. }
  72. res.json({
  73. ...BaseStdResponse.OK,
  74. data: r.data.url
  75. })
  76. } catch (error) {
  77. this.logger.error(`获取聚合登录链接失败!${error.message || 'api接口错误'}`)
  78. return res.json({
  79. ...BaseStdResponse.ERR,
  80. msg: '请尝试其他登录方式或稍后再试!'
  81. })
  82. }
  83. }
  84. }
  85. module.exports.GetLoginUrl = GetLoginUrl;