对于前后端分离时,用户权限设计的一点思考

Posted by Lain on 10-13,2019

在模板引擎时代,对于用户权限的管理是后台的事情,无论是对于API的请求限制,还是对页面内容渲染的控制,比如对按钮级别的元素进行显示与隐藏,这些在模板引擎中都不是问题,各个模板引擎也开发了大量标签,帮助我们对页面上要显示的内容进行控制。

但如今前后端分离的开发方式已经流行很长一段时间了,前后端各司其职,后端只需要提供数据,对于接口的访问进行鉴权,并干涉不到页面的渲染结果。而前端并拿不到权限信息,对于一些需要不同权限显示隐藏或禁用某些元素的需求,似乎只能让后端把权限信息传递过来,在渲染页面的时候进行区分。

首先要明确一点,前端的权限校验实际上是掩耳盗铃的,如果是对内容进行权限区分,是需要后台在传数据的时候就区分开,如果传到前端再区分,一个F12就全看到了,这就没有意义了。接口的权限要和前端的权限校验同步,这里说的前端权限校验,是指【视觉】上的,比如管理员在其他用户的主页上,可以看见一个设置按钮,点开后能看到一个面板,里面包含了对用户进行的各种操作。在前后端分离的情况下,如果前端不做限制,普通的用户都能轻松的看到管理员能进行的全部操作,虽然他们在点击这些按钮的时候,后端只会返回权限异常,但让普通用户知道管理员能干什么,明显对于运维来说是很不利的。当然,这种用户管理类的需求,我们可以采用【管理后台】的方式来解决,管理员的所有操作都放到后台来进行,这就是需求上的差异了。

对于内容权限,我们不希望未登录用户看到网站中的内容,那么在请求内容的时候,后端就应该返回鉴权状态码与提示信息,前端根据状态码来进行提示,这里没有什么问题。

另一方面,现在很多前端项目都是单页面应用,通过前端路由来对页面的访问进行控制,同样,对于用户能否访问到某个模块,也需要根据权限进行拦截。

但同时,我们不可能在每次请求发起前,或是用户进行操作前都发请求到后台请求权限需求,没人希望对着自己服务器来一场人工DDOS,除了明日方舟的基建系统(没错,我说的就是你,贸易站!)

我的想法是,后端在设计权限的时候,多设计一类供前端使用的权限,我把它叫做视图权限。
视图权限可以任意起名,但必须唯一,推荐使用URI路径,将 / 改为 :,然后接上具体要控制权限的组件名,建议是组件的id,或是自行命名。没错,就和Shiro对接口权限的命名一样,这样就能保证权限名的唯一,而且很有辨识度。
当加载前端页面时,在渲染前,向后端请求该用户拥有的所有【角色】以及【视图权限】,我们就叫它权限字典吧,在渲染时进行判断,如果不允许访问的组件,一律不渲染。
当然,有需要的话,在前端路由也进行拦截,如果某个路径被配置了访问权限,而用户的权限字典里没有的话,直接跳转到403页面。
我画了一个简单的说明图:

1

2

3

4

当然,我们还要考虑权限更新的问题,实际上前文也说过,前端权限控制只是【视觉】上的权限控制,如果后台对用户的权限进行了变更,而用户正好在浏览页面的话,那么他依旧是能看到原权限所拥有的页面的,但如果他试图进行越权操作,那也是不可能的,因为接口的权限是实时生效的,即使前端的权限字典没有及时更新,用户也无法对后台进行任何越权操作,在他下次刷新页面后,前端拿到了新的权限字典,那新权限也会跟着生效。