实现统一门户登录跳转免登录

发布于:2025-08-28 ⋅ 阅读:(14) ⋅ 点赞:(0)

统一门户所有应用页面,点击跳转对应业务系统,实现业务系统免登录

//获取所有业务系统项(获取并存储到仓库)
//用于页面展示
let appSubjectVoList = ref<any>([])
appSubjectVoList.value = userStore.getAppSubjectVoList || []
//登陆后获取ticket 存储
const ticket = userStore.getTicket || ''
//当前项目编码
const PATH_URL = import.meta.env.VITE_APP_BASE_URL
//当前路由
const webclientHost = window.location.protocol + '//' + window.location.host
//token及用户信息皆为登录时获取存储到仓库
//点击业务系统图标跳转,item就是appSubjectVoList的每一项
const jumpApp = (item) => {
  let data = {
    appCode: item.appCode,
    appName: item.appName,
    parentCode: item.parentCode,
    securityNetworkUrl: item.securityNetworkUrl,
    securityNetworkUrlConnected: appAvailability.value[item.appCode], // 使用检测结果
    schoolNetworkUrl: item.schoolNetworkUrl,
    schoolNetworkUrlConnected: true,
    webClientHost: webclientHost,
    ticket: ticket,
    token: userStore.getToken,
    account: userStore.getUserInfo?.account,
    appType: 0,
    useType: item.useType
  }
  postAndRedirect(`${PATH_URL}/uil/redirect`, data)
}

//由后端重定向跳转
/**
 * 以POST方式提交数据并处理接口重定向
 * 接口重定向后会在新窗口打开目标页面
 * @param {string} apiUrl - 后端接口地址(会重定向的接口)
 * @param {object} postData - 需要传递的POST参数
 */
async function postAndRedirect(apiUrl, postData) {
  try {
    const response = await fetch(apiUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(postData),
      redirect: 'manual'
    })

    if (response.status === 302) {
      const redirectUrl = response.headers.get('Location')
      window.open(redirectUrl, '_blank')
    } else {
      const data = await response.json()
      if (data.data && data.code == 200) {
        window.open(data.data, '_blank')
      }
      if (data.code == 401) {
        userStore.logout()
      }
    }
  } catch (error) {
    console.error('Error:', error)
  }
}

业务系统接收处理页面

  1. 新建 UILLogin 页面(@/views/Login/UILLogin.vue),作为接收并处理 Ticket 的转换页面
  • 根据项目 Code 获取对应的 applicationId(用于菜单获取)。
  • 接收统一门户跳转时传递的参数:appCode、ticket、uilBackendUrl 和 grantId,存入 uilLogindata 对象。
  • 调用业务系统提供的 Token 换取接口(uilLogin),传入 uilLogindata。若接口调用成功,则执行与常规登录相同的后续流程(如获取用户信息、权限菜单等并存储);若失败,则拦截并跳转至登录页。
  • 若统一门户跳转时指定了目标模块(redirect 参数),则登录成功后跳转至该模块;否则跳转至菜单首项。
  • <script setup lang="ts">
    import { computed, reactive, ref } from 'vue'
    import { useRouter, useRoute } from 'vue-router'
    import { uilLogin } from '@/api/login'
    import { useAppStore } from '@/store/modules/app'
    import { usePermissionStore } from '@/store/modules/permission'
    import { useUserStore } from '@/store/modules/user'
    import type { RouteRecordRaw } from 'vue-router'
    import { userDetail, menuAccountTree } from '@/api/login'
    import { processMenuData } from '@/utils/tree'
    import { ElMessage, ElScrollbar } from 'element-plus'
    import { applicationInfo } from '@/api/sys/index'
    
    const { addRoute, push } = useRouter()
    const appStore = useAppStore()
    const permissionStore = usePermissionStore()
    const route = useRoute()
    const userStore = useUserStore()
    const redirect = ref('')
    let uilLogindata = reactive({
      appCode: '',
      ticket: '',
      uilBackendUrl: '',
      grantId: ''
    })
    if (route.query?.ticket && typeof route.query.ticket === 'string') {
      uilLogindata.ticket = route.query.ticket
    }
    if (route.query?.appCode && typeof route.query.appCode === 'string') {
      uilLogindata.appCode = route.query.appCode
    }
    if (route.query?.uilBackendUrl && typeof route.query.uilBackendUrl === 'string') {
      uilLogindata.uilBackendUrl = route.query.uilBackendUrl
    }
    if (route.query?.redirect && typeof route.query.redirect === 'string') {
      redirect.value = route.query.redirect
    }
    if (route.query?.grantId && typeof route.query.grantId === 'string') {
      uilLogindata.grantId = route.query.grantId
    }
    //更改为项目code~~~~~~~~~~~~~~~~~~~~~~~~~
    const BASE_PATH = import.meta.env.VITE_BASE_PATH
    // 根据需求 获取applicationId
    const getapplicationId = () => {
      applicationInfo(BASE_PATH).then((res) => {
        if (res.code == 200) {
          appStore.setSysInfo(res.data)
          // ticket登录~~~~~~~~~~~~~~~~~~~~~~~~
          if (uilLogindata.ticket) {
            uilLogin(uilLogindata)
              .then(async (res) => {
                if (res.code == 200) {
                  userStore.setToken(res.data.tokenValue)
                  userStore.setTokenKey(res.data.tokenName)
                  if (appStore.getDynamicRouter) {
                    getUser()
                  } else {
                    await permissionStore.generateRoutes('static').catch(() => {})
                    permissionStore.getAddRouters.forEach((route) => {
                      addRoute(route as RouteRecordRaw) // 动态添加可访问路由表
                    })
                    permissionStore.setIsAddRouters(true)
                    // 有指定页面跳转指定页面~~~~~~~~~~~~~~~~~~~~~~~~
                    if (redirect.value) {
                      push(`/${redirect.value}`)
                    } else {
                      push({ path: permissionStore.addRouters[0].path })
                    }
                  }
                } else {
                  push('/login')
                }
              })
              .catch(() => {
                push('/login')
              })
          } else {
            // 没有ticket回到登录页
            push('/login')
          }
        } else {
          ElMessage.error('网络异常,请返回重新跳转!')
        }
      })
    }
    getapplicationId()
    const application = computed(() => appStore.getSysInfo)
    // 获取角色信息
    const getUser = async () => {
      const resmenu = await menuAccountTree({ applicationId: application.value.id })
      resmenu.data = processMenuData(resmenu.data, true, true)
      const res = await userDetail()
      res.data.menus = resmenu.data
      // console.log(res, 'res')
      if (res) {
        if (!res.data.menus || !res.data.menus.length) {
          ElMessage({
            type: 'error',
            message: '用户没有权限'
          })
          userStore.logout()
          return
        }
        userStore.setUserInfo(res.data)
        const routers: any[] = res.data.menus || []
        // console.log(routers, 'routers')
        userStore.setRoleRouters(routers)
        appStore.getDynamicRouter && appStore.getServerDynamicRouter
          ? await permissionStore.generateRoutes('server', routers).catch(() => {})
          : await permissionStore.generateRoutes('frontEnd', routers).catch(() => {})
        console.log(permissionStore.getAddRouters, 'permissionStore.getAddRouters')
        permissionStore.getAddRouters.forEach((route) => {
          addRoute(route as RouteRecordRaw) // 动态添加可访问路由表
        })
        permissionStore.setIsAddRouters(true)
        // 有指定页面跳转指定页面~~~~~~~~~~~~~~~~~~~~~~~~
        if (redirect.value) {
          push(`/${redirect.value}`)
        } else {
          push({ path: permissionStore.addRouters[0].path })
        }
      }
    }
    </script>
    <template>
      <div>
        <ElScrollbar class="h-full">
          <div
            class="lt-sm:p-10px dark:bg-[var(--login-bg-color)] mx-auto h-100vh flex justify-center items-center"
          >
            跳转中...
          </div>
        </ElScrollbar>
      </div>
    </template>
    <style lang="less" scoped></style>
  • 在路由配置(router.ts)中添加 /uil-login 页面,确保该页面可被访问。
 {
    path: '/uil-login',
    component: () => import('@/views/Login/UILLogin.vue'),
    name: 'uilLogin',
    meta: {
      hidden: true,
      title: 'UIL登录',
      noTagsView: true
    }
  },
  • 将 /uil-login 加入免重定向白名单(NO_REDIRECT_WHITE_LIST),避免在该页面触发登录重定向逻辑。
export const NO_REDIRECT_WHITE_LIST = ['/login', '/uis-login', '/uploadPage', '/uil-login']

在 @/api/login.ts 中新增 uilLogin 后端 Token 换取接口。

// uil免登录
export const uilLogin = (data): Promise<IResponse> => {
  return request.post({ url: `/uil/login`, data })
}


网站公告

今日签到

点亮在社区的每一天
去签到