spring-security,有没有对需要权限控制的 url 存入数据库的实现。 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
zhaoxixiangban
V2EX    程序员

spring-security,有没有对需要权限控制的 url 存入数据库的实现。

  •  1
     
  •   zhaoxixiangban 2020-06-19 10:45:24 +08:00 4177 次点击
    这是一个创建于 1947 天前的主题,其中的信息可能已经有所发展或是发生改变。
    29 条回复    2020-06-21 08:23:44 +08:00
    admin7785
        1
    admin7785  
       2020-06-19 11:23:44 +08:00 via iPhone
    我用了 rabbitmq,获取方法的接口信息 然后拼接存入数据库
    jorneyr
        2
    jorneyr  
       2020-06-19 11:29:05 +08:00
    考虑过这个问题,基于链接的授权:
    1. Spring Security 中设置所有 (某些) 链接都需要角色 USER 才能访问
    2. AuthenticationFilter 获取用户登录信息时 (基于 token) 查询用户是否可以访问此链接,如果可以设置角色为 USER 使得其有权访问,否则设置为没有权限的用户角色如 NO 即可
    siweipancc
        3
    siweipancc  
       2020-06-19 12:18:51 +08:00 via iPhone
    你这个,可以用 PreAuth 注解,在 el 引用一个 验证 bean 对现有凭据进行拦截。我待会写一个 demo 看看。
    skypyb
        4
    skypyb  
       2020-06-19 12:49:10 +08:00 via Android
    。。。不就是接口级权限么,网上实现应该很多啊。spring security 里有授权管理器,自己重写一遍覆盖掉默认的就行了
    hantsy
        5
    hantsy  
       2020-06-19 13:24:13 +08:00
    实现不难,但是完全没必要。国内很多需求都是扯蛋的,一般项目几种 Role 就基本可以了。

    以前一个项目,客户要求实现自己 一套颗粒度很细的权限管理,自己可以编辑配置。实现过程要花点时间,难度不大,全部( API 的 URLPattern,HTTPMETHOD,一条不同操作对应一条授权 Permission )保存到数据库,用户页面可以打开授权,整页面都是 CheckBox 的 Permissions,客户看到那个后自己都晕了,感觉自己蠢了。
    ourslay
        6
    ourslay  
       2020-06-19 13:35:41 +08:00
    https://docs.spring.io/spring-security/site/docs/5.4.0-M1/reference/html5/#el-access-web-beans
    `
    public class WebSecurity {
    public boolean check(Authentication authentication, HttpServletRequest request) {
    ...
    }
    }
    You could refer to the method using:

    <http>
    <intercept-url pattern="/user/**"
    access="@webSecurity.check(authentication,request)"/>
    ...
    </http>
    or in Java configuration

    http
    .authorizeRequests(authorize -> authorize
    .antMatchers("/user/**").access("@webSecurity.check(authentication,request)")
    ...
    )
    `
    Reactive 应用就更简单
    `
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
    http
    .authorizeExchange()
    .pathMatchers("/api/**").access(customerAccessCheck)
    ...
    return http.build();
    }
    `
    siweipancc
        7
    siweipancc  
       2020-06-19 13:42:57 +08:00
    // ---------model
    @Entity
    @Data
    @Accessors(chain = true)
    public class AuthUrl implements Serializable {
    @Id
    @GeneratedValue
    private Long id;

    private String url;

    @ElementCollection
    private List<Long> uIds;
    }

    // ----- 控制层 @PreAuthorize("@userProfileManager.currentUserAuthForUlr(authentication,httpServletRequest.requestURL.toString())")
    @PutMapping("password")
    public ResponseEntity<String> changePassword(@RequestParam String newPassword, Authentication authentication) {
    profileManager.changePassword(newPassword, authentication);
    return ResponseEntity.ok("success");
    }

    // -------- service
    public class UserProfileManager {
    // 各种注入
    public boolean currentUserAuthForUlr(Authentication authentication, String url) {
    Optional<UserProfile> optiOnal= userProfileMapper.findOne(Example.of(new UserProfile().setEmail(authentication.getPrincipal().toString())));
    UserProfile profile = optional.orElseThrow(() -> new BadCredentialsException("请重新登录"));
    AuthUrl authUrl = authUrlMapper.findOne(Example.of(new AuthUrl().setUrl(url))).orElse(null);
    if (authUrl == null) {
    return true;
    }
    List<Long> uIds = authUrl.getUIds();
    return uIds == null || uIds.isEmpty() || uIds.contains(profile.getId());
    }


    public void changePassword(String newPassword, Authentication authentication) {
    Optional<UserProfile> optiOnal= userProfileMapper.findOne(Example.of(new UserProfile().setEmail(authentication.getPrincipal().toString())));
    UserProfile profile = optional.orElseThrow(() -> new BadCredentialsException("请重新登录"));
    String encode = passwordEncoder.encode(newPassword);
    profile.setPassword(encode);
    userProfileMapper.saveAndFlush(profile);
    }
    // **
    }
    tctc4869
        8
    tctc4869  
       2020-06-19 15:47:56 +08:00
    @hantsy 你的权限系统的思路,能说明一下么?
    zhaoxixiangban
        9
    zhaoxixiangban  
    OP
       2020-06-19 15:59:13 +08:00
    @skypyb #4 需要前端进行自定义配置角色权限的,类似五楼的需求。- - 汗 ,所以需要把可配置的权限都给到前端
    Vegetable
        10
    Vegetable  
       2020-06-19 16:01:03 +08:00
    目测 xy problem
    zhaoxixiangban
        11
    zhaoxixiangban  
    OP
       2020-06-19 16:02:06 +08:00
    @siweipancc #7 嗯 现在后台权限这边问题不大,像上面五楼说的类似,需要用户对细粒度的权限进行自定义配置,就需要我们把相应的接口数据都存起来给前端,接口列表数据部分都是怎么实现的呢?手动加数据库?
    zhaoxixiangban
        12
    zhaoxixiangban  
    OP
       2020-06-19 16:04:36 +08:00
    @hantsy #5 对就是这种需求 ,操作接口是自己手动加数据库吗
    zhaoxixiangban
        13
    zhaoxixiangban  
    OP
       2020-06-19 16:05:39 +08:00
    @jorneyr #2
    @ourslay #6
    抱歉是我没有说清楚 ,问题点是五楼阐述的这种状况。
    zhaoxixiangban
        14
    zhaoxixiangban  
    OP
       2020-06-19 16:06:29 +08:00
    @admin7785 #1 具体怎么个搞法
    siweipancc
        15
    siweipancc  
       2020-06-19 18:20:35 +08:00 via iPhone
    @zhaoxixiangban 我建议你不要这么玩,最后双头坑,角色或者组跟模块绑定的设计才能继续维护。
    daimubai
        16
    daimubai  
       2020-06-19 22:11:38 +08:00
    手动加数据库,然后加载权限信息到用户,最后配置全局权限控制;
    zhenjiachen
        17
    zhenjiachen  
       2020-06-20 08:31:29 +08:00 via iPhone
    看一下我的实现,可能有 bug,不过可以借鉴一下。https://github.com/chenzhenjia/niubi-commons/blob/master/README.md
    hantsy
        18
    hantsy  
       2020-06-20 10:59:21 +08:00
    @ourslay URL 没有动态配置。
    @siweipancc 很好的利用 Spring Security 更简单。
    @zhaoxixiangban @tctc4869
    思路:
    1, 权限定义用一个表( JPA Entity ),类似结构:
    name 唯一,另外( urlPattern 与 httpMethod )组合唯一。

    Permission{
    name//唯一,比如 PERM_GET_ALL_POSTS
    urlPattern//比如:/posts/*
    httpMethod// 比如:GET, 可用 enum 或直接用 Spring web HttpMethod. 常用的有 GET,POST,PUT,DELETE,PATCH
    longDescription//其它辅助说明(用于页面补充)
    }

    那么 user 与 Permission 权限关系:
    user->permission 1:n

    2. Repository 类,PermissionRepository
    3. Spring Security 中直接使用 Apply 。

    allPermissiOns= permissionRepository.findAll(Sort.by(...))

    http
    .authorizeRequests(authorize ->
    allPermissions.forEach(perm->{
    authorize
    .antMatchers(per.urlPattern, per.httpMethod).hasAuthority(perm.name)//这里查 Spring Security 文档,我记得以前不用 AntMatcher,而使用 RegexMatcher,表达比 ANT 方式更丰富。
    })

    4. 配置一个超级管理员,绕过所有权限(不读数据库),可以维护系统的 permission 列表。
    默认给定一个管理员,配置所有权限。管理员可以用管理用户,可以管理用户权限(页面可以是 Checkbox,或者两列选择,等),最终影响 user -> permission 关系表。
    所有新注册用户默认应该协商好,应该给那些权限,可以设计一些 DUMMY 权限比如 READ,那么在 persmission 表所有 httpmethod GET 权限就拿到了( UserDetailsService 中转换成实际 permissions 的 Authories )。
    5. (扩展) 所有权限的初始数据可以用 Reflection 生成,在系统启动时初始化(添加,更新)。
    6. (扩展) 可以添加 Role,role->Permission 可以是一对多的关系, 相当于权限分组了。在 UserDetailsService 的 findByusername 将所有的 Role 转换成 Permission 添加到 authories 中(因为上面的 Spring Security 中只配置比较 Permission )。这样的话,数据库关系变成 user->role>permission 1:n,1:n 。
    7. (扩展) 所有前端的权限可以登录时拿到一个个人的允许的 permission 列表,可以用来辅助前端的页面控制。比如没有授权 PERM_GET_ALL_POSTS 的时候,可以从页面把顶级菜单上的 posts 去掉了。API 资源本身就是可以归类的,我从来没用过 V 站那些资源共享版本中贴的那些什么功能模块与权限配置表。

    我遵循的一个原则,用户细粗度的行为(一个点击,一个操作)在一个应用程序中基本是可以固定下来的。所以 每一个不同操作最终变成一个不同的权限,Permission 在你的项目(应用)上线时候,基本可以是固定下来的,而 Role 完全可以由用户随便添加,随意修改。
    hantsy
        19
    hantsy  
       2020-06-20 11:01:39 +08:00
    user->permission,user->role>permission 应该都是 n:m 多对多。
    hantsy
        20
    hantsy  
       2020-06-20 11:14:14 +08:00
    回到之前的观点:完全没必要这样灵活设计。之前加了 ROLE 之后 ,ROLE A 包含了 perm a, ROLE B 没有包含 perm a 。那么问题,遇到客户一个用户添加了 A,B,它觉得莫名其妙的来了,为什么 ROLE B 没有 perm a,我(用户)却有 perm a 。那么更复杂的问题来了,当一个用户设置了 ROLE, A,B,C,D,那么是不是要用户去决定 A,B,C,D 之间的权限是继承还是覆盖关系???

    这种灵活设计,对用户和开发人员都是作茧自缚,用处不大,技术没含量,很费事。基本过去十几年的项目经验可以肯定的说,基本上都是可以固定的 ROLE 搞定,结果大量的时间去开发所有权限系统。为什么用户会强调 ROLE 要灵活配置,说白了一点,从需求角度来分析,就是它自己需求不确定,不知道要做什么东西。
    zzl22100048
        21
    zzl22100048  
       2020-06-20 11:43:04 +08:00 via iPhone
    看 keycloak 的细粒度权限控制
    hantsy
        22
    hantsy  
       2020-06-20 14:03:06 +08:00
    @zzl22100048 Keycloak 推荐过好多次了。国内没几个人用的,在 V 站看到的人都是觉得自己开发的权限 /安全系统最好的。
    tctc4869
        23
    tctc4869  
       2020-06-20 17:39:10 +08:00
    @hantsy 问一下,ABAC 与 RBAC 两种权限模型,有什么本质区别么?没用过 ABAC 权限模型,我目前接触到的权限体系就是关于 RBAC 的,有博客说 ABAC 的权限配置比 RBAC 更灵活,配置权限也更复杂。到底是怎么样的呢?
    tctc4869
        24
    tctc4869  
       2020-06-20 17:49:54 +08:00
    @hantsy 浏览了很多有关权限系统的说明博客,关于 ABAC 权限体系,如果要在用途归纳起来,我感觉就是基于平台应用级别的权限系统,不同的组织,在这个平台上,可以有不一样的权限体系。至少每个组织对内权限体系,可以不一样。而 RBAC 权限模型做不到这一点,或者说很困难,至少如果有两个客户群体对内有不一样的权限需求,RBAC 实现起来就会很困难。是这样的么?比如做一个面向多企业客户级别的平台应用,那么权限系统采用 ABAC 是最合适的么
    hantsy
        25
    hantsy  
       2020-06-20 20:22:43 +08:00
    这个自己 Google 下吧,https://www.dnsstuff.com/rbac-vs-abac-access-control#rbac-vs-abac
    我只关注过 RBAC,似乎 Java EE 标准体系也只有基于 ROLE (和 Group,同等 ROLE )的设计。
    hantsy
        26
    hantsy  
       2020-06-20 20:36:36 +08:00
    ABAC 看介绍这只是更细一些,而且是另外一个方向。
    RBAC 以 ROLE,行为(权限)为基础的。

    ABAC 更的多关注对一个资源的个别属性的访问控制权限,更细的控制。这个除非是基于传统数据模型的的开发,比如传统的 MIS 之类的系统。我觉得用在 API 的控制不大可能 。传统基于数据的开发,实现也不难。以前的 JBoss 下的 http://picketlink.org/ 应该相应的方案,记得见过了。数据模型,比如 JPA Entity,每个属性用某个 Annotation 标注,全部运行时可以提取出来 ,一样可以存放在数据库或者基于 LDAP 这种层层目录访问的方式 ,然后剩下就是就是在数据 CRUD 操作下控制了。
    hantsy
        27
    hantsy  
       2020-06-20 20:52:28 +08:00
    @tctc4869 很多时候面对客户,只是把有些东西在脑子里面想得太复杂。中国人这种细粒度的控制,说白了也是我们文化的一部分,控制欲太强了。国外角色更多是系统上的分工,国内的讲权限(实际国内客户很少跟谈角色这个词,很多没有角色这个概念)更多的讲操控上的权力,可以授权,可以取消授权。

    其实只要弄清楚,归类出来有几种人可以用这个系统(应用),角色就可以满足。欧美的项目我做很多,有电商,有支付,没有一个要这个种权限配置系统 。有些项目,人家一开始需求就很明确的提出了有几种人用这个系统,操作方式上有应该什么差别。
    tctc4869
        28
    tctc4869  
       2020-06-21 07:47:47 +08:00 via Android
    @hantsy 那我有另一个问题,如果有一个项目,要面向不同类型的客户群体,而且可能每个客户群体内部有不一样的权限需求。这个时候权限系统要怎么配置,若是在 rbac 权限体系下,是进行角色分类上的不同的客户关系扩展,还在重新做针对客户需求的一套应用?还是用 abac 模型体系下设计呢?
    hantsy
        29
    hantsy  
       2020-06-21 08:23:44 +08:00
    业务相关的权限本身就和开公的一些权限标准(规范等)没太大的关系,自己根据业务需求决定了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2555 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 02:13 PVG 10:13 LAX 19:13 JFK 22:13
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86