V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
tctc4869
V2EX  ›  Java

Java 有现成的权限系统框架么?

  •  1
     
  •   tctc4869 · 2020-06-18 20:25:05 +08:00 · 8721 次点击
    这是一个创建于 1652 天前的主题,其中的信息可能已经有所发展或是发生改变。

    之前自己开发 web 项目的时候,关于权限系统的编码,自己从 0 开始编写了一个简易的权限系统,基于 RBAC 的那种,不过还是想看看有没有现成的权限系统设计。

    现在的我不太喜欢注解配置,注解侵入太强,想找一套式非侵入式的权限系统框架,权限校验在类似 Web 拦截器之类的地方进行权限校验。各位知道有哪些现成的么,或者有什么思路么

    至于是哪个 WebMVC 框架,这里不说明,因为 WebMVC 框架可能使用的是 Spring MVC,也可能是 Vert.x web,也可能是 JFinal,也可能是 Servlet 。所以侵入程度不要太强。尽可能与 WebMVC 的代码解耦。这是一个重点。

    权限校验代码不能写在 Controller 类里,所以 shiro 之类通过注解的方式实现权限校验的方式被排除了,如果有 Controller 需要特定的权限校验,那这个交给拦截器之类的组件来进行。

    第 1 条附言  ·  2020-06-19 19:49:41 +08:00
    没用过 abac 权限模型,abac 相对 RBAC 简单么?我记得有网站说 abac 比 rbac 权限模型,虽然灵活,但配置相对复杂。是这样的么?关于 abac 权限,有哪些好的资料说明呢
    54 条回复    2020-10-17 22:23:01 +08:00
    byaiu
        1
    byaiu  
       2020-06-18 20:44:25 +08:00
    shiro 可以吗
    beginor
        2
    beginor  
       2020-06-18 20:52:24 +08:00 via Android   ❤️ 1
    最近也在看 spring 全家桶, 但是似乎没有像 asp.net core identity 同等级别的认证框架,Java 不太熟, 无意引战, 有的话望各路大神告知
    tctc4869
        3
    tctc4869  
    OP
       2020-06-18 21:04:12 +08:00
    @byaiu 这个不行
    Sharuru
        4
    Sharuru  
       2020-06-18 21:33:09 +08:00
    轻量的比较少,以前用过几个,但是实现不咋地,要 customize 一下很烦。
    现在框架流行注解是为了易用,一句话就能解决的东西就不用再像以前 XML 里写茫茫多的代码了;也符合 Spring Boot 的风格。

    话说回来,其实几个叫得出名字的验证框架其最终还是利用 Filter 来满足功能的。

    比如 Spring Security 就是其中之一,把预制好的,各种各样来源、功能的 Filter 注册到 Web 访问的生命周期中来实现自己的验证链。

    翻阅一下 AuthenticationChain 的代码,或者官方文档的 Security Filter Chain 章节,楼主就应该能有思路自己撸一套喜欢的验证框架了。
    zifangsky
        5
    zifangsky  
       2020-06-18 21:33:25 +08:00
    试试我写的这个权限控制框架?名字叫:easylimit ( https://github.com/zifangsky/easylimit

    如果不喜欢注解形式,可以类似下面这样配置:
    https://i.loli.net/2020/06/18/TRnWw1o8NJ6Vjl4.jpg
    chihiro2014
        6
    chihiro2014  
       2020-06-18 21:44:40 +08:00
    Spring Security 不香么
    sadfQED2
        7
    sadfQED2  
       2020-06-18 21:51:07 +08:00 via Android
    权限系统跟业务耦合太严重了,还是自己写比较好,以后改也好改
    tctc4869
        8
    tctc4869  
    OP
       2020-06-18 22:25:13 +08:00 via Android
    @Sharuru
    我不喜欢注解配置权限的原因是,注解是硬编码。
    tsdbg
        9
    tsdbg  
       2020-06-19 00:40:03 +08:00
    Vert.x 如何?直接在 Router 里校验
    xuanbg
        10
    xuanbg  
       2020-06-19 02:31:53 +08:00
    xuanbg
        11
    xuanbg  
       2020-06-19 02:41:02 +08:00
    @sadfQED2 只要有资源管理和资源对应的接口配置,就可以达成完全无耦合的目标。底层原理就是用可配置的约定替代依赖而已,比较形象点的说法就是对暗号,只认暗号不认人。
    lihongming
        12
    lihongming  
       2020-06-19 03:27:59 +08:00 via iPhone
    自从用了 AWS Serverless 框架,就再也不写权限系统了,只需规划好路径,Cognito 和 APIGateway 会自动拦截无权访问的。

    这种按路径控制权限的思想通用型很好,我觉得应该有现成的框架(可惜我不知道)
    yukiloh
        13
    yukiloh  
       2020-06-19 03:35:14 +08:00
    @lihongming 是不是通过 lambda 来调用.前段时间想研究的,我是 idea19.1,aws toolkit 版本高了报错,低了还是报错,最后火大了一键卸载
    wangxiaoaer
        14
    wangxiaoaer  
       2020-06-19 06:56:52 +08:00 via Android
    @lihongming 跟由层实现的只能是基本的能不能访问的情况,但如果同一个接口需要根据角色返回不同数据,实现不了吧。
    waa
        15
    waa  
       2020-06-19 07:14:26 +08:00 via Android
    @wangxiaoaer 这种怎么实现
    inwar
        16
    inwar  
       2020-06-19 07:22:57 +08:00 via Android
    @wangxiaoaer 路由大粒度,服务小粒度
    lihongming
        17
    lihongming  
       2020-06-19 07:31:52 +08:00 via iPhone
    @wangxiaoaer 根据角色返回不同数据就不算“权限”控制的范畴了吧?

    这种需求似乎没什么可用的框架,都得自己根据用户的 group id 或者 role id 自己写规则
    Hanggi
        18
    Hanggi  
       2020-06-19 08:05:26 +08:00
    @wangxiaoaer 你这样不就把角色和其他数据耦合在一起了吗?
    jzphx
        19
    jzphx  
       2020-06-19 08:27:56 +08:00
    注解侵入强,属硬编码不能认同。既然都 RBAC 了,菜单角色权限都在 db 或者缓存,可配置性很强。不在 controller 控制权限不科学啊,难道控制的不是菜单权限而是数据权限?放在 service 层对业务侵入肯定强啊
    wangyanrui
        20
    wangyanrui  
       2020-06-19 08:33:29 +08:00
    1. 权限基本高度耦合业务
    2. 越轻量越需要自己定制,越重量约可以多组合起来,少定制
    2. SpringSecurity 基本满足楼主要求,虚拟出来一个 FIlter 链去做权限校验,只需要导 starter,切换成数据库,配配配即可
    tctc4869
        21
    tctc4869  
    OP
       2020-06-19 09:00:31 +08:00
    @jzphx 菜单角色权限都在 db 的话,我可以直接通过后台管理界面配置权限,通过 web 拦截器校验权限,这样没注解什么事情了。另外我开头说明中,指定了没有指明是用哪个 WebMVC 框架,要在这个情况下考虑比较通用的权限校验问题。至于特殊的权限校验,那是另外的事情。

    注解本来就是硬编码,一旦运行就不可更改(如果需要要改注解对象内容,那还要注解干什么?相比注解,还有更好的配置方式,是建造者模式与链式调用)。
    hantsy
        22
    hantsy  
       2020-06-19 09:06:14 +08:00   ❤️ 1
    @beginor Spring Security 以前的 Oauth 子项目有一个 Authentication Server 实现, 现在这个项目处于维护状态。

    https://spring.io/projects/spring-security-oauth

    现在这新的 Spring Security 5 核心包括了 OAuth2 模块,完全重写了。目前核心还没包括 Authenticaiton Server,从安全的角度看,这个不属于安全控制的一些部分,Spring Security 的 OAuth Client 和 Resource Server 的实现可以与任何兼容 OAuth2 和 OIDC 协议的 Authentitcation Server 交互。

    不过,Spring 启动一个新的社区项目。
    https://github.com/spring-projects-experimental/spring-authorization-server

    其实现在做安全,只要选择一个 OAuth 兼容的认证服务就行了,如果应用程序不大(像淘宝,天猫),没必要自己建 auth server,可以选择第三方 IDP 服务,如 auth0,okta 都不错。自建的话,现成的开源产品很多,基于 .DotNet Core Identity Server, Redhat 的 Keycloak (基本很多自建的首选),Spring 母公司的之前 Uaa(现在在 CloudFoundry 下面), https://github.com/cloudfoundry/uaa
    wangxiaoaer
        23
    wangxiaoaer  
       2020-06-19 09:13:59 +08:00
    @lihongming #17 严格讲算的,最典型的部门、人员这种带层级的架构,那么一般数据可见范围是要控制在本部门的。
    tctc4869
        24
    tctc4869  
    OP
       2020-06-19 09:14:59 +08:00
    @tsdbg 这不是 WebMVC 框架的问题,与 Vert.x 或 Sring MVC 等无关,要抛开 WebMVC 框架,单独来看待 Web 权限校验。
    wangxiaoaer
        25
    wangxiaoaer  
       2020-06-19 09:22:22 +08:00
    @Hanggi #18

    我能想到的一种方案:所有跟权限相关的查询属性都作为查询参数,然后还是路由层进行控制。

    比如针对这样一个需求:经理角色再查询用户的时候只能看到本部门的用户,并且只能看到姓名这个字段

    1 用户接口的粒度要足够细:查询部门、查询字段要作为参数显式声明(客户端提供)

    2 用户接口严格按照查询参数做查询,这一步不做验证工作。

    2 路由层根据查询参数做过滤实现授权和权限验证,这个过滤就可以借助一些配置文件实现相对的通用。
    qq1340691923
        26
    qq1340691923  
       2020-06-19 09:24:44 +08:00   ❤️ 1
    这也不愿意,那也不愿意,你是来引战的吧
    tctc4869
        27
    tctc4869  
    OP
       2020-06-19 09:27:55 +08:00
    @qq1340691923 自说自话,先射箭,后画靶子
    tctc4869
        28
    tctc4869  
    OP
       2020-06-19 09:33:53 +08:00
    @wangxiaoaer 权限配置,除了考虑 OA 系统的组织体系,还有客户体系。

    比如有些权限无法手动配置,由业务逻辑配置,比如客户申请某类资源的使用,后台审核能否客户使用,审核通过就会赋予客户用户对某类资源的角色权限,这个时候权限就会侵入到业务里,对于这类你有什么好的解耦思路。
    wizzer
        29
    wizzer  
       2020-06-19 09:40:36 +08:00
    wangxiaoaer
        30
    wangxiaoaer  
       2020-06-19 09:44:15 +08:00
    @tctc4869 #28 这跟我之前说的思路不冲突,审核通过后赋予了某个客户某个新的权限,那么把这个权限信息写入到路由验证所依赖的那个配置文件中就可以了啊。

    “ 路由层根据查询参数做过滤实现授权和权限验证,这个过滤就可以借助一些配置文件实现相对的通用。”

    这个地方刚没有细说,单实际上整个权限验证的核心就是这一块,他将权限规则抽象成表达式的方法存到某个配置中,又能够解析表达式在路由层结合请求参数做过滤。这个配置可以是文件也可以是数据库,所以既放置预先配置好的规则,当然也可以在运行时更新。
    zengyuxi
        31
    zengyuxi  
       2020-06-19 09:45:28 +08:00
    什么叫抛开 webMVC 框架?你确定不是过来逗我们玩的?你了解“Spring Security”吗?提问题之前,先问是不是,再问为什么!
    tctc4869
        32
    tctc4869  
    OP
       2020-06-19 10:04:10 +08:00
    @wangxiaoaer 关于这个思路,有链接提供完整的说明么?
    wucao219101
        33
    wucao219101  
       2020-06-19 10:05:20 +08:00
    Spring Security +1
    wangxiaoaer
        34
    wangxiaoaer  
       2020-06-19 10:09:08 +08:00
    @tctc4869 #32 没有啊。 我只是瞎捷豹想的啊,但是感觉应该有可行性。
    tctc4869
        35
    tctc4869  
    OP
       2020-06-19 10:16:41 +08:00
    @wangxiaoaer 我有个想法,我的开头有说明是脱离 WebMVC 框架,来思考权限校验,我想搞一个 HttpContext 的 java 抽象类,然后我的权限校验就基于该抽象类体系进行。如果要较好的处理权限校验的话,这个抽象类应该添加哪些设计了?
    hantsy
        36
    hantsy  
       2020-06-19 10:38:37 +08:00
    @tctc4869 你说这些纯粹是你的业务需求(权限设置),和业务绑定自己要实现,用什么安全架构,框架,技术有什么关系?
    ixx
        37
    ixx  
       2020-06-19 14:03:02 +08:00
    试试 keycloak?
    Alex5467
        38
    Alex5467  
       2020-06-19 14:07:56 +08:00
    @byaiu 他都说 shiro 之类通过注解的方式实现权限校验的方式被排除了
    safilar
        39
    safilar  
       2020-06-19 15:40:47 +08:00
    @tctc4869 你这种需求很简单,shiro 那种到处要写注解在代码里面确实有一些问题,比如开发自己忘记写了,变成只有前端走个校验了。
    BQsummer
        40
    BQsummer  
       2020-06-19 15:44:11 +08:00
    我顺便问个题外话,rbac 肯定满足不了中等公司的需求,abac 有啥落地方案吗,我们现在公司是自研的权限系统,基于树的,很绕,介于 rbac 和 abac 之间,很多功能修修补补
    safilar
        41
    safilar  
       2020-06-19 15:58:03 +08:00
    @tctc4869 其实就是重写一个拦截器,将接口上的注解直接映射到 redis,这里需要自己建存储。然后统一由拦截器读取配置,这里用 spring Security 举例子重写 AccessDecisionManager decide 的方法。第一个参数 Authentication 是你自定义的权限集合(一般读表);第二个参数,一般取 request 用的,
    safilar
        42
    safilar  
       2020-06-19 16:01:10 +08:00
    第三个参数 urlConfigAttribute 用户传递过来的 uri,你通过这个方法直接鉴权;如果是权限路由表是 pathvariable 这种,你就可以使用 AntPathRequestMatcher spring 自带的识别器来做权限识别是否匹配。
    safilar
        43
    safilar  
       2020-06-19 16:02:42 +08:00
    无论是 rbac 还是 abac 这种方式实现都是比较简单,至少注解不用写了。
    wangxiaoaer
        44
    wangxiaoaer  
       2020-06-19 16:04:27 +08:00 via Android
    @BQsummer abac 结合 spring expression 我觉得有搞头。
    tctc4869
        45
    tctc4869  
    OP
       2020-06-19 19:40:43 +08:00
    @safilar
    没用过 abac 权限模型,abac 相对 RBAC 简单么?我记得这个有网站说 abac 比 rbac 权限模型,要复杂。是这样的么?
    xuanbg
        46
    xuanbg  
       2020-06-19 21:10:47 +08:00
    @tctc4869 你这个需求其实是多租户体系的典型应用。对于多租户体系来说,每个租户都有独立的角色权限管理。譬如淘宝店铺后台就是个多租户应用,钉钉也是。我们都是阿里的用户,在我们注册店铺后,店铺就是阿里的租户,我们既是阿里的普通用户,也是店铺这个租户的管理用户。

    这些概念对于没深入有研究过权限管理系统的人来说可能稍复杂,但可以简单看一下 https://github.com/xuanbg/auth 这个项目里面的表结构。
    xuanbg
        47
    xuanbg  
       2020-06-19 21:11:52 +08:00
    tctc4869
        48
    tctc4869  
    OP
       2020-06-20 17:45:16 +08:00
    @xuanbg 根据你所说的,ABAC 权限体系的用途上,我感觉,就是基于平台应用级别的权限系统,不同的组织,在这个平台上,可以有不一样的权限体系。至少每个组织对内权限体系,可以不一样。而 RBAC 权限模型做不到这一点,至少如果有两个客户群体有不一样的权限需求,RBAC 实现起来就会很困难。是这样的么?
    xuanbg
        49
    xuanbg  
       2020-06-20 19:55:13 +08:00
    @tctc4869
    权限其实就是资源的分配,而资源的集合就是应用。最原始的 RBAC,只是不考虑多租户,而且是单应用的权限数据模型。

    而在多租户多应用体系里面,你所谓的客户群体,本质上都是用户而已。你把他们看做两个群体,实际上不过是他们是两个应用的用户罢了。

    我项目里面的 role 表中,tenant_id 表示角色的租户归属,app_id 表示角色的应用归属。也就是同样应用的管理员,A 租户和 B 租户是两个角色,他们各管各的且互相不可见。

    具体的关系,你看我这篇博客就明白了。https://www.cnblogs.com/xuanbg/p/12511509.html
    fox0001
        50
    fox0001  
       2020-06-20 21:04:32 +08:00 via Android
    权限应该分为功能权限和数据权限。

    功能权限的话,filter ( Web 拦截器)应该是比较适合了。

    数据权限的话,很大程度依赖根据业务逻辑而设计的数据结构。
    Shikyou
        51
    Shikyou  
       2020-06-24 16:07:16 +08:00
    @hantsy 也可以试一下国内的 Authing 。
    authing.cn 和 cognito / auth0 / okta 差不多,可以快速实现用户的 ABAC 和 RBAC
    hantsy
        52
    hantsy  
       2020-06-24 16:45:19 +08:00
    @Shikyou AUTHING.CN 这种方向不错,不过国内推广应该没有国外那么容易。以前在项目推荐过 Stormpath (后来被 Okta 收购了)。国内的对于推荐一些方案如果他们自己没有弄过的,基本上我之前一些帖子见到那些言论一样,“用这个出了问题来谁背锅”,“你不能证明这个我们用的更好,为什么要换掉现成的东西”,“迁移到其它平台风险你能评估出来吗,这个工作量算谁的”。国内公司家长式的管理模式,培养都是一些巨婴一样的员工,不管什么方案,对于他们只要不要他们重新学习,不要他们动手就是最好的方案,每天用用 Copy,Paste 就完成工作就好了。

    接触国外到项目,自己没太多要求的基本都是走一下 JWT Token 完成了,有社交账号支持要求的,多种形式认证( 2fa, otp 等)的基本最终上线选择 okta 或 outh0 这些成熟方案比较多,有些使用的 API 或者方案是自己都是集成身份认证了,比如 Firebase 。开发过程中可能就是直接用一个 Basic Http 认证,对于大部分功能写测试比较简单。
    Shikyou
        53
    Shikyou  
       2020-06-24 16:57:27 +08:00
    @hantsy 草。分析得太对了。感谢对 Authing 的认可,我们在小范围推广 ing
    hsluoyz
        54
    hsluoyz  
       2020-10-17 22:23:01 +08:00
    推荐下 jCasbin: https://github.com/casbin/jcasbin 支持 ACL 、RBAC 、ABAC 等访问控制模型
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1160 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 18:31 · PVG 02:31 · LAX 10:31 · JFK 13:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.