2月复盘:把“一直想做但没做”的前端安全开始了

2 阅读2分钟

2月很短,过个年回来就剩几个工作日。但我们团队干了一件一直想干但总是“没时间”的事——前端安全大规模排查


为什么现在做?

说实话,安全这东西,平时总觉得“应该没问题”,等出了问题就晚了。这次趁着年初业务相对平稳,我们决定把历史欠账还上。

排查清单很简单,就8条:

text

所有用户输入都转义了?(XSS)
敏感操作加二次确认了?(CSRF)
页面禁止被iframe嵌入了?(点击劫持)
console.log删干净了?(信息泄露)
页面/按钮做了权限控制?(越权)
最近跑过npm audit吗?(依赖安全)
全站HTTPS了吗?(传输安全)
token存对地方了吗?(存储安全)

其中XSS和越权是最常见、出事最严重的。2月我们重点啃了越权这块硬骨头。


越权整改:我们本来就不差,这次更完善了

坦白说,我们在越权这块底子还可以:

  • ✅ 路由守卫拦页面,没权限的直接403
  • ✅ 权限指令统一管理按钮,不用到处写v-if
  • ✅ 敏感操作二次确认,防误点也防CSRF

那这次改版加了什么?一个关键拼图:在菜单上配置对应接口


以前的问题:页面能看,但接口能调吗?

之前我们是这么做的:

用户登录 → 拿菜单权限 → 渲染左侧菜单 → 路由守卫拦页面

看起来没问题,但有个漏洞:菜单和接口是脱节的

举个例子:

  • 普通用户看不到“审批管理”菜单(√ 没问题)
  • 但他如果知道接口地址,用Postman调/api/order/approve(× 能调通!)

因为后端只判断“用户有没有登录”,没判断“这个接口对应用户能不能调”。


这次改了:菜单和接口绑定

核心改动就一句话:每个菜单项配置对应的接口权限,后端拦截时拿菜单做校验

改了什么?

1. 菜单数据结构升级

javascript

// 以前的菜单
{
  name: '审批管理',
  path: '/approve',
  icon: 'xxx'
}

// 现在的菜单
{
  name: '审批管理',
  path: '/approve',
  icon: 'xxx',
  apiPermissions: [
    '/api/order/approve',
    '/api/order/list?status=pending',
    '/api/order/batchApprove'
  ]  // 这个菜单下所有操作对应的接口
}

2. 最重要的是:前后口径一致了

后端收到请求/api/order/approve,拿着token查这个用户对应的菜单配置:

  • 如果这个接口在用户菜单里 → 放行
  • 如果不在 → 直接提示没有权限

一点体会

  1. 权限的核心是统一。菜单、按钮、接口,得用同一套数据源。
  2. 前端做体验,后端做安全。这次改版让后端能拿菜单做校验,安全防线更扎实了。
  3. 之前底子好,这次补短板。路由守卫+权限指令+二次确认,加上菜单配接口,算是把越权的口子全堵上了。