1
admin7785 2020-06-19 11:23:44 +08:00 via iPhone
我用了 rabbitmq,获取方法的接口信息 然后拼接存入数据库
|
2
jorneyr 2020-06-19 11:29:05 +08:00
考虑过这个问题,基于链接的授权:
1. Spring Security 中设置所有 (某些) 链接都需要角色 USER 才能访问 2. AuthenticationFilter 获取用户登录信息时 (基于 token) 查询用户是否可以访问此链接,如果可以设置角色为 USER 使得其有权访问,否则设置为没有权限的用户角色如 NO 即可 |
3
siweipancc 2020-06-19 12:18:51 +08:00 via iPhone
你这个,可以用 PreAuth 注解,在 el 引用一个 验证 bean 对现有凭据进行拦截。我待会写一个 demo 看看。
|
4
skypyb 2020-06-19 12:49:10 +08:00 via Android
。。。不就是接口级权限么,网上实现应该很多啊。spring security 里有授权管理器,自己重写一遍覆盖掉默认的就行了
|
5
hantsy 2020-06-19 13:24:13 +08:00
实现不难,但是完全没必要。国内很多需求都是扯蛋的,一般项目几种 Role 就基本可以了。
以前一个项目,客户要求实现自己 一套颗粒度很细的权限管理,自己可以编辑配置。实现过程要花点时间,难度不大,全部( API 的 URLPattern,HTTPMETHOD,一条不同操作对应一条授权 Permission )保存到数据库,用户页面可以打开授权,整页面都是 CheckBox 的 Permissions,客户看到那个后自己都晕了,感觉自己蠢了。 |
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(); } ` |
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); } // ** } |
9
zhaoxixiangban OP @skypyb #4 需要前端进行自定义配置角色权限的,类似五楼的需求。- -· 汗 ,所以需要把可配置的权限都给到前端
|
10
Vegetable 2020-06-19 16:01:03 +08:00
目测 xy problem
|
11
zhaoxixiangban OP @siweipancc #7 嗯 现在后台权限这边问题不大,像上面五楼说的类似,需要用户对细粒度的权限进行自定义配置,就需要我们把相应的接口数据都存起来给前端,接口列表数据这部分都是怎么实现的呢?手动加数据库?
|
12
zhaoxixiangban OP @hantsy #5 对就是这种需求 ,操作接口是自己手动加数据库吗
|
13
zhaoxixiangban OP |
14
zhaoxixiangban OP @admin7785 #1 具体怎么个搞法
|
15
siweipancc 2020-06-19 18:20:35 +08:00 via iPhone
@zhaoxixiangban 我建议你不要这么玩,最后双头坑,角色或者组跟模块绑定的设计才能继续维护。
|
16
daimubai 2020-06-19 22:11:38 +08:00
手动加数据库,然后加载权限信息到用户,最后配置全局权限控制;
|
17
zhenjiachen 2020-06-20 08:31:29 +08:00 via iPhone
看一下我的实现,可能有 bug,不过可以借鉴一下。https://github.com/chenzhenjia/niubi-commons/blob/master/README.md
|
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 完全可以由用户随便添加,随意修改。 |
19
hantsy 2020-06-20 11:01:39 +08:00
user->permission,user->role>permission 应该都是 n:m 多对多。
|
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 要灵活配置,说白了一点,从需求角度来分析,就是它自己需求不确定,不知道要做什么东西。 |
21
zzl22100048 2020-06-20 11:43:04 +08:00 via iPhone
看 keycloak 的细粒度权限控制
|
22
hantsy 2020-06-20 14:03:06 +08:00
@zzl22100048 Keycloak 推荐过好多次了。国内没几个人用的,在 V 站看到的人都是觉得自己开发的权限 /安全系统最好的。
|
23
tctc4869 2020-06-20 17:39:10 +08:00
@hantsy 问一下,ABAC 与 RBAC 两种权限模型,有什么本质区别么?没用过 ABAC 权限模型,我目前接触到的权限体系就是关于 RBAC 的,有博客说 ABAC 的权限配置比 RBAC 更灵活,配置权限也更复杂。到底是怎么样的呢?
|
24
tctc4869 2020-06-20 17:49:54 +08:00
@hantsy 浏览了很多有关权限系统的说明博客,关于 ABAC 权限体系,如果要在用途归纳起来,我感觉就是基于平台应用级别的权限系统,不同的组织,在这个平台上,可以有不一样的权限体系。至少每个组织对内权限体系,可以不一样。而 RBAC 权限模型做不到这一点,或者说很困难,至少如果有两个客户群体对内有不一样的权限需求,RBAC 实现起来就会很困难。是这样的么?比如做一个面向多企业客户级别的平台应用,那么权限系统采用 ABAC 是最合适的么
|
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 )的设计。 |
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 操作下控制了。 |
27
hantsy 2020-06-20 20:52:28 +08:00
@tctc4869 很多时候面对客户,只是把有些东西在脑子里面想得太复杂。中国人这种细粒度的控制,说白了也是我们文化的一部分,控制欲太强了。国外角色更多是系统上的分工,国内的讲权限(实际国内客户很少跟谈角色这个词,很多没有角色这个概念)更多的讲操控上的权力,可以授权,可以取消授权。
其实只要弄清楚,归类出来有几种人可以用这个系统(应用),角色就可以满足。欧美的项目我做很多,有电商,有支付,没有一个要这个种权限配置系统 。有些项目,人家一开始需求就很明确的提出了有几种人用这个系统,操作方式上有应该什么差别。 |
28
tctc4869 2020-06-21 07:47:47 +08:00 via Android
@hantsy 那我有另一个问题,如果有一个项目,要面向不同类型的客户群体,而且可能每个客户群体内部有不一样的权限需求。这个时候权限系统要怎么配置,若是在 rbac 权限体系下,是进行角色分类上的不同的客户关系扩展,还在重新做针对客户需求的一套应用?还是用 abac 模型体系下设计呢?
|
29
hantsy 2020-06-21 08:23:44 +08:00
业务相关的权限本身就和开公的一些权限标准(规范等)没太大的关系,自己根据业务需求决定了。
|