跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Java大前端java

ruoyi-vue-pro 数据大屏纯前端单点登录实现

ruoyi-vue-pro 数据大屏模块默认需账号密码登录,本方案利用 OAuth2 授权机制改造前端代码,通过新增回调组件、路由拦截及 API 配置,实现单点登录无缝跳转,提升用户体验。主要步骤包括注册应用、修改 callback 页面、配置 SSO 路由与 API、以及在路由守卫中处理未认证状态。

神经兮兮发布于 2026/3/30更新于 2026/10/2693 浏览
ruoyi-vue-pro 数据大屏纯前端单点登录实现

ruoyi-vue-pro 已集成数据大屏模块 go-view,支持通过拖拽生成精美的大屏应用。然而点击【报表管理->大屏设计】时默认需要输入账号密码登录,体验不佳。

文章配图

ruoyi-vue-pro 已支持应用注册及 OAuth2 授权功能,但最后一公里需自行实现。以下是改造步骤:

1. 在【三方授权->应用管理】中注册数据大屏应用 report

文章配图

2. 改造 yudao-ui-go-view-master 项目支持断点登录

A) 新增 callback 组件

新增页面 src/views/sso/callback.vue,内容如下:

<template>
  <div></div>
</template>

<script lang="ts" setup>
import { reactive, ref, onMounted } from 'vue'
import { Router, useRoute } from 'vue-router'
import { ssoLoginCallbackApi } from '@/api/path'
import { useSystemStore } from '@/store/modules/systemStore/systemStore'
import { SystemStoreUserInfoEnum, SystemStoreEnum } from '@/store/modules/systemStore/systemStore.d'
import { StorageEnum } from '@/enums/storageEnum'
import { PageEnum, PreviewEnum } from '@/enums/pageEnum'
import { routerTurnByName } from '@/utils'
import { getTenantIdByNameApi, getUserInfoApi, loginApi } from '@/api/path'

const systemStore = useSystemStore()
const t = window['$t']

onMounted(async () => {
  const route = useRoute()
  const code = route.query.code
  if (!code) {
    return
  }
  var loginRes = await ssoLoginCallbackApi(code.toString())
  if (loginRes && loginRes.data) {
    // ① Token 信息(先存储下,保证可以加载个人信息)
    const tokenValue = loginRes.data.access_token
    const tokenName = 'Authorization'
    systemStore.setItem(SystemStoreEnum.TENANT_INFO, { tenantId: 1 })
    systemStore.setItem(SystemStoreEnum.USER_INFO, {
      [SystemStoreUserInfoEnum.USER_TOKEN]: tokenValue,
      [SystemStoreUserInfoEnum.TOKEN_NAME]: tokenName
    })
    // 个人信息
    const profileRes = await getUserInfoApi()
    const id = profileRes?.data?.id
    const username = profileRes?.data?.username
    const nickname = profileRes?.data?.nickname
    if (id && username && nickname) {
      // 存储到 pinia
      systemStore.setItem(SystemStoreEnum.USER_INFO, {
        [SystemStoreUserInfoEnum.USER_TOKEN]: tokenValue,
        [SystemStoreUserInfoEnum.TOKEN_NAME]: tokenName,
        [SystemStoreUserInfoEnum.USER_ID]: id,
        [SystemStoreUserInfoEnum.USER_NAME]: username,
        [SystemStoreUserInfoEnum.NICK_NAME]: nickname
      })
      window['$message'].success(t('login.login_success'))
      var sso_url = localStorage.getItem(StorageEnum.GO_SSO_URL)
      console.log('sso_url:' + sso_url)
      if (sso_url) {
        localStorage.removeItem(StorageEnum.GO_SSO_URL)
        window.location.href = sso_url
        return
      }
      routerTurnByName(sso_url || PageEnum.BASE_HOME_NAME, true)
      return
    }
    window['$message'].error('登陆失败:' + profileRes.msg)
    routerTurnByName(PageEnum.ERROR_PAGE_NAME_403, true)
  } else {
    window['$message'].success(loginRes.msg)
    window['$message'].error('登陆失败:' + loginRes.msg)
    routerTurnByName(PageEnum.BASE_LOGIN_NAME, true)
  }
})
</script>

B) 新增 callback 路由

在 src/router/base.ts 中找到 LoginRoute,在后面新增代码:

export const SsoCallbackRoute: RouteRecordRaw = {
  path: PageEnum.SSO_CALL_BACK,
  name: PageEnum.SSO_CALL_BACK_NAME,
  component: () => import('@/views/sso/callback.vue'),
  meta: {
    title: '单点登录',
  },
};

在 src/router/index.ts 文件中导入。

文章配图

C) 新增单点登录 API

数据大屏为内网环境,后端使用 ruoyi-vue-pro,appKey 和 appSecret 暂时写死在 JS 中,后期可配置到后端 application.yaml。

文章配图

在 src/api/path/system.api.ts 中,找到 logoutApi,在其后新增单点登录 API 如下:

// * SSO 登录
// 可以改写成,你的 clientId
const clientId = 'yudao-sso-demo-by-code';
export const ssoLogin = () => {
  const redirectUri = encodeURIComponent('http://localhost:3000/callback');
  // 注意,需要使用 encodeURIComponent 编码地址
  const responseType = 'code';
  // 1)授权码模式,对应 code;2)简化模式,对应 token
  window.location.href = 'https://192.168.1.222:80/sso?client_id=' + clientId + '&redirect_uri=' + redirectUri + '&response_type=' + responseType;
}

// * SSO 登录
export const ssoLoginCallbackApi = async (code: String) => {
  try {
    const redirectUri = "http://localhost:3000/callback";
    const url = "https://192.168.1.222:80/admin-api/system/oauth2/token?grant_type=authorization_code&code=" + code + "&redirect_uri=" + redirectUri;
    const params = {};
    const headers = {
      "Content-Type": ContentTypeEnum.JSON,
      "tenant-id": "1",
      "Authorization": "Basic " + encode(new TextEncoder().encode(clientId + ":datav123"))
    };
    const config = { baseURL: '', headers: headers };
    var res = await axios.post(url, params, config);
    console.log(res);
    return res.data;
  } catch (err) {
    httpErrorHandle();
  }
};

// 单点登录 callback 中调用,查询用户个人信息
export const getUserInfoApi = async () => {
  try {
    const res = await http(RequestHttpEnum.GET)<ProfileVO>(`${ModuleTypeEnum.SYSTEM}/oauth2/user/get`);
    return res;
  } catch (err) {
    httpErrorHandle();
  }
};

D) 在路由守卫中拦截 sso

在 src/router/router-guards.ts 文件中判断白名单前,新增代码如下:

if (to && to.query && to.query.sso == 'true') {
  localStorage.setItem(StorageEnum.GO_SSO_URL, window.location.href);
  // @ts-ignore
  if (!routerAllowList.includes(to.name) && !loginCheck()) {
    ssoLogin();
    return;
  }
}

E) 处理后端返回未认证(状态码为 401)

在 src/api/axios.ts 中新增代码,如果 sso 访问但未登录成功或者 token 超时则发起单点登录。

文章配图

3. 改造 yudao-vue-pro 中的【报表管理->大屏设计】中的页面

文章配图

只需在 URL 上加一个参数 sso=true 即可。

4. 验证访问数据大屏

A) 验证单点登录

重新启动 yudao-vue-pro、yudao-ui-go-view,或刷新【报表管理->大屏设计】,将会出现授权请求页面如下:

文章配图

这个页面是 yudao-vue-pro 中的 src/views/sso.vue,这里只是改了样式,通常不需要改动。同意授权后页面会自动跳转到数据大屏的首页。

文章配图

授权一次以后就可以访问了。

B) 验证在 yudao-vue-pro 中配置菜单直接访问数据看板

文章配图

目录

  1. 1. 在【三方授权->应用管理】中注册数据大屏应用 report
  2. 2. 改造 yudao-ui-go-view-master 项目支持断点登录
  3. A) 新增 callback 组件
  4. B) 新增 callback 路由
  5. C) 新增单点登录 API
  6. D) 在路由守卫中拦截 sso
  7. E) 处理后端返回未认证(状态码为 401)
  8. 3. 改造 yudao-vue-pro 中的【报表管理->大屏设计】中的页面
  9. 4. 验证访问数据大屏
  10. A) 验证单点登录
  11. B) 验证在 yudao-vue-pro 中配置菜单直接访问数据看板

更多推荐文章

查看全部
  • Python 入门:30 个常用技巧与最佳实践
  • Neo4j 社区版安装与使用指南
  • JavaScript Proxy 代理机制与核心方法详解

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online