浅谈权限设计(从接口权限到数据权限)

太久没写了,今天补一篇,本篇无实际代码,主要是设计思路。

关于JWT:在我所开发的系统中用户Token都是有意义的,都会携带部分数据,不过多用于userId

个人的权限系统使用历程:

基于Security(不加表、角色放在Token中)

  • 注解验证(乱七八糟)
    使用Spring Security框架,将用户角色ROLE_USER写在account表中,UserDetailsService的实现方法中封装UserDetails返回,然后在接口上添加注解进行权限校验
    好处是简单,但是权限写在逻辑里面了。改权限就要发版本,小系统可以这样干
  • 请求地址前缀验证(分模块)
    顾名思义,按照角色划分接口地址,类似于微服务模块拆分,但是这个纯粹就是为了权限验证拆。而且说实话也不好升级。

RBAC模型

用户表、角色表、功能表、接口表、关联表
在这里插入图片描述
凑活看。不过后面的很多思路都是基于这个表结构的。

  • RBAC数据库
    实现AccessDecisionManager接口

    FilterInvocation filterInvocation = (FilterInvocation) object;
    Set<String> uris = smsAccountRoleMapper.uris((String) authentication.getPrincipal());
    if (uris.contains(filterInvocation.getRequestUrl())) {
        return;
    } else {
        log.info("当前请求路径:[{}]用户权限为:[{}]", filterInvocation.getRequestUrl(), uris);
        throw new AccessDeniedException("权限不足");
    }
    

    到这里就已经实现接口权限动态配置了,但是同时到此也全都是没营养的废话,下面开始更经典的。

  • 使用Redis+JWT
    Redis用于存储JWT、JWT用来存储用户标识
    实现AuthorizationServerTokenServicescreateAccessTokenrefreshAccessToken方法,不需要实现TokenStore,直接写在MyTokenService里就行、就是一堆Token生成存储逻辑、从JWT的实现类里面拷贝一部分,再拷贝一部分Redis的就组合成了。

    技巧:以下所有存储,Redis有效期设置尽量比真实的有效期短1小时,防止Redis验证通过而Token解析失败

    前缀含义
    UNAME_TO_ACCESS用户标识>>>accessToken、主要用于用户封号冻结时删除Token及单设备登录限制
    ACCESS_TO_USERaccessToken >>>userId、鉴于Token为JWT生成,所以此处仅用于验证Token真实性
    ACCESS_TO_REFRESHaccessToken >>>refreshToken 、账号冻结时删除当前账号所有有关的Token信息
    REFRESH_TO_ACCESSrefreshToken >>> accessToken、刷新令牌仅可以使用一次、且用完之后需要删除旧的accessToken
    REFRESHrefreshToken信息、用于刷新令牌

    验证逻辑
    1、开放性接口直接过
    2、需要登录的由Redis负责校验是否为真实有效的Token
    3、需要进行权限校验的依靠数据库RBAC关系进行查询校验。

  • 微服务
    其实微服务和前面的一样,认证中心发放Token,网关验证鉴权、所有的逻辑基本一致

  • 前端按钮验证
    在这里要安利一个开源项目:若依,给了我很多启发。
    上文表结构接口表中有一个字段为前端验证key,具体使用方式为后端在用户登录之后返给前端一个Set集合,前端在组件中封装一个标签,类似v-if,参数为这个按钮的验证key,如果Set集合中有就显示,没有就不显示按钮。
    下图是若依的验证逻辑,考虑的非常周到,一个按钮可能对应多个接口:
    在这里插入图片描述
    建议:尽量和后端接口名保持一致,因为后端接口你不可能提供两个相同的(尽量使用PostMapping

  • 前端页面验证
    页面相较于按钮复杂之处在于后端的一个接口会在多个页面调用且一个页面会调用后端多个接口,所以后端提供路由配置就显得不是那么方便,所以我的思路是:前端知道当前页面会调用哪些接口,而且也知道哪些接口有权限验证,同时考虑到前端某些数据可能今天在这里展示,明天就换位置了,所以将页面级的路由交于前端自行校验,具体逻辑为:
    1、当前页面存在开放性接口,如查询,那么直接展示
    2、当前页面所有接口都需要权限,那么验证后端返回的Set集合中是否和当前页面的接口验证key存在交集,如果有展示,如果没有隐藏

DBAC模型

顾名思义:同一个接口,不同的人访问看到的数据是不一样的,这个不一样不是指看到的自己的数据不一样,而是同样一个页面,你只能看自己的,老师能看班级的,校长能看全校的。

数据权限一定要根据系统实际使用进行设计,虽然有某些通用的设计方案,但是如果直接拿过来使用而不加以设计那么一定会面临性能问题。

  • 统一权限
    某人对系统的操作等级是固定的,只在角色变更时变化,那么可以使用若依的那套实现方式,MyBatis拦截器的方式,然后判断用户权限等级拼接SQL后缀、不过若依那一套简单,SQL基本固定,因为他的部门角色是基础实现。
  • 拆分权限
    一个用户对于系统中的不同接口的访问权限是不同的,不单单是部门的问题(例如一个部门的部长犯了错误,公司让他回家反省,那么他还是部长,但是可能他再登录系统就只能看自己的数据了)
    思路:将前端的验证思路搬到后端,在MyBatis接口上添加注解,在拦截器中判断当前用户对于当前SQL的权限等级是什么,查询出不同的SQL后缀拼接到查询语句中。
    在这里插入图片描述
    知道用户、mapper接口、那么就能查看对应的SQL后缀是什么,进行动态拼接就可以了。

欢迎留言,有时间也搞个开源项目大家玩玩。

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Lasso,全称Least Absolute Shrinkage and Selection Operator,是一种常用的回归算法。它在线性回归的基础上引入了L1正则化项,通过对系数进行约束,使得模型的权重更加稀疏,即对不重要的特征进行了去除或减弱。 Lasso的优点在于它能够在高维数据中进行特征选择,避免了过拟合问题。通过减少不重要特征的权重,它能够更好地处理多重共线性的情况。Lasso算法的目标函数是通过最小化均方误差和L1正则化项的和来实现的。 Lasso算法在实际应用中具有广泛的应用。首先,由于Lasso能够进行特征选择,它在特征工程中非常有用。在处理具有大量特征的数据时,Lasso能够帮助我们找到最重要的特征,从而简化模型,提高预测准确率。其次,Lasso也用于稀疏信号恢复,包括图像压缩和恢复、语音处理等领域。另外,Lasso也可以用于分类问题,例如在基因表达数据中的药物响应预测。 然而,Lasso也存在一些限制。首先,由于L1正则化的特性,Lasso在存在高度相关特征的情况下可能会选择其中一个特征,并将其系数置为零,而忽略其他高度相关的特征。其次,Lasso是一个线性模型,对于非线性问题可能效果较差。此外,Lasso对于数据中存在较多噪声的情况可能表现不佳。 总体而言,Lasso算法是一种强大的回归算法,在特征选择和稀疏信号恢复等领域有广泛的应用。但在具体应用时,需要根据问题的特点和数据的特征来进行合理的选择和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值