微搭低代码MBA培训管理系统实战09——页面级权限过滤与无权限拦截

目录

前情回顾与本节目标

在上一讲中,我们成功实现了多角色门户的登录与路由分发。当超级管理员登录后,点击工作台入口,系统会通过 $w.utils.reLaunch 路由到我们的部门管理页面。

但这里存在一个安全漏洞:如果员工把"部门管理"页面的 URL 直接复制发给没有权限的人,或者没有权限的用户手动在浏览器输入了该地址,系统该如何拦截?

本节我们就来解决这个核心问题,为具体的业务页面(以"部门管理"页为例)加上"安全锁"。

本节核心目标:

  1. 获取鉴权入参:在页面加载时,获取全局对象中的用户标识以及当前页面的标识。
  2. 数据源鉴权逻辑:通过自定义 JavaScript 方法,查询该用户所属的角色是否被分配了该页面的访问权限。
  3. 条件渲染拦截:利用微搭组件的"条件展示"属性,有权限则展示业务内容,无权限则展示拦截提示。

第一步:页面状态变量准备

在进入写代码之前,我们需要在部门管理页面中定义两个页面级变量,用来控制 UI 的加载与展示。

在页面设计器右侧的"代码区" -> "当前页面" -> 点击"新建变量":

变量名称 类型 初始值 说明
isLoading 布尔值 true 用于控制骨架屏或Loading状态,页面刚进入时正在鉴权,默认为 true
hasPermission 布尔值 false 用于标记当前用户是否有权限,校验通过后设为 true

注:设置 isLoading 是为了防止在异步请求未返回时,页面出现短暂的"闪烁"或数据暴露。



第二步:编写权限校验自定义方法

在"代码区" -> "当前页面",点击"新建 JavaScript 方法",命名为 checkPagePermission

这段代码的核心思路是:从全局状态中获取用户的角色信息,然后根据这些角色从数据库中查询对应的页面权限,检查用户是否拥有访问当前页面的权限。

复制以下代码并粘贴:

javascript 复制代码
export default async function ({ event, data }) {
  try {
    // 1. 从全局状态中获取当前登录用户的信息和角色
    const currentUser = $w.app.dataset.state.currentUser;
    const userRoles = $w.app.dataset.state.userRoles || [];
    
    // 当前页面的唯一标识,与我们在 实战07 中创建的 Pages 表里的 pageId 保持一致
    const currentPageId = $w.page.id; 

    // 如果没有用户信息或用户信息不完整(可能是没登录,或者全局状态丢失)
    if (!currentUser || !currentUser._id) {
      $w.page.dataset.state.hasPermission = false;
      $w.utils.showToast({ title: '未获取到登录信息,请重新登录', icon: 'error' });
      // 可选:直接将其踢回登录页
      // $w.utils.reLaunch({ pageId: '你的登录页ID' }); 
      return;
    }

    // 2. 查询用户角色对应的页面权限
    let hasAuth = false;
    
    if (userRoles.length > 0) {
      // 根据用户角色查询角色信息,获取页面权限
      const roleRes = await $w.cloud.callDataSource({
        dataSourceName: 'MBA_Roles', // 替换为你的角色表标识
        methodName: 'wedaGetRecordsV2',
        params: {
          filter: {
            where: {
              code: { $in: userRoles }
            }
          },
          select: {
            $master: true,
            can_access_pages: true // 角色的页面权限字段
          }
        }
      });

      // 检查用户是否有权限访问当前页面
      if (roleRes.records && roleRes.records.length > 0) {
        for (const role of roleRes.records) {
          const authPages = role.can_access_pages || [];
          // 检查当前页面是否在角色的权限列表中
          const isMatch = authPages.some(page => page.pageId === currentPageId || page._id === currentPageId);
          if (isMatch) {
            hasAuth = true;
            break;
          }
        }
      }
    }

    // 3. 将鉴权结果写入页面变量
    $w.page.dataset.state.hasPermission = hasAuth;

  } catch (error) {
    console.error('权限校验异常:', error);
    $w.page.dataset.state.hasPermission = false;
    $w.utils.showToast({ title: '权限校验失败,请联系管理员', icon: 'error' });
  } finally {
    // 4. 无论鉴权成功与否,结束 Loading 状态
    $w.page.dataset.state.isLoading = false;
  }
}

第三步:页面生命周期绑定

鉴权方法写好了,我们需要让它在页面刚加载的时候就立即执行。

  1. 点击左侧大纲树最顶部的 "页面:部门管理" 节点。
  2. 在右侧属性面板找到 "事件" 配置。
  3. 找到页面显示 (show)事件。
  4. 点击添加事件,选择 "自定义 JavaScript 方法" -> 选择我们刚才写好的 checkPagePermission

注:推荐绑定在 onShow(页面显示)上,这样即使用户通过浏览器的前进后退按钮返回该页面,也会重新触发鉴权,安全性更高。


第四步:配置组件的"条件展示"

这是实现无权限拦截的关键步骤:我们将通过组件的属性,决定给用户看什么。

1. 配置真实业务内容的条件展示

  1. 在大纲树中,选中包裹你部门管理页面所有核心业务内容的最外层容器网格布局。
  2. 在右侧属性面板找到 "条件展示"
  3. 将默认的开关关闭,点击右侧的 fx(表达式绑定)。
  4. 输入表达式:
javascript 复制代码
$w.page.dataset.state.hasPermission

这意味着:只有当鉴权方法跑完,并且结果为 true 时,这块业务内容才会被渲染到页面上。

2. 搭建"无权限提示"占位图

  1. 在大纲树的最外层(与刚才的业务容器平级),拖入一个新的 "普通容器"
  2. 在这个新容器里,放入一个"图标"组件(可以选择一个警告或拦截的 icon)和一个"文本"组件(写上:"抱歉,您暂无权限访问此页面,请联系系统管理员。")。你还可以放一个按钮,点击后调用 $w.utils.navigateBack 返回门户页。
  3. 选中这个无权限提示的容器,在右侧找到 "条件展示"
  4. 绑定表达式:
javascript 复制代码
$w.page.dataset.state.hasPermission === false && $w.page.dataset.state.isLoading === false


这意味着:只有当鉴权结束(加载完成)且结果明确为无权限时,才展示这个提示容器。

(进阶:你还可以为 isLoading === true 单独写一个 Loading 动画容器,逻辑同理)


最终效果

现在,让我们来检验这道"安全锁":

  1. 正常路径测试:使用配置了管理员角色的账号登录门户,点击"进入管理员工作台"。页面一闪而过极短的 Loading,瞬间展示出完整的左树右表"部门管理"界面。
  2. 越权路径测试 :退出登录,用一个只有"学员端"权限的普通账号登录。强行在浏览器地址栏输入刚才部门管理页面的 URL 回车。页面加载完成后,核心业务数据完全不可见,屏幕中央仅显示:"抱歉,您暂无权限访问此页面"

权限隔离完美生效!


总结

本节我们在"微搭"平台上,用极其标准的前端鉴权思路,补齐了整个系统 RBAC (Role-Based Access Control) 的闭环:

  1. 鉴权时机 :在页面生命周期 onShow 时拦截。
  2. 数据打通 :联动了 Users -> RoleUsers -> Roles,实现了精准的页面粒度权限验证。
  3. 前端渲染控制 :利用微搭的条件展示特性,做到数据的物理隔离,防止前端数据泄露。

通过这 8 篇文章的实战,我们的 MBA 培训管理系统已经拥有了一个无比坚固且灵活的底层架构。

下一步,我们将真正深入业务深水区! 我将带大家进入【业务员工作台】,实现核心的 "客户与商机管理(CRM)" 模块,学习如何在微搭中实现复杂的表单联动、线索公海掉落机制。敬请期待!

相关推荐
Zoho低代码开发工具2 小时前
如何用低代码两周交付国际物流追踪系统?
低代码
低代码布道师2 小时前
微搭低代码MBA培训管理系统实战10——渠道管理
低代码
液态不合群2 小时前
AI赋能下的中国低代码市场:从工具革新到产业数字化核心引擎
java·人工智能·低代码·架构
卷积殉铁子1 天前
低代码实体识别平台设计:当工作流引擎遇上NLP服务
低代码·nlp·工作流引擎
决斗小饼干1 天前
低代码平台工作流引擎设计:从状态机到智能流转的技术演进
前端·低代码·工作流引擎
掘金安东尼2 天前
活动落地页效率翻倍:RollCode 这次更新有点猛
前端·低代码·面试
宏天软件BPM_低代码3 天前
宏天低代码平台实时协作方案:基于OT算法的原创实现与优化实践
低代码
葡萄城技术团队3 天前
写给技术管理者的低代码手册系列文章(8)——第二部分:低代码的概念、价值与发展现状(第四章)
低代码
树上有只程序猿3 天前
继续堆无用代码,真的不如早点用Low code
前端·低代码