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

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

以前一个项目,客户要求实现自己 一套颗粒度很细的权限管理,自己可以编辑配置。实现过程要花点时间,难度不大,全部( API 的 URLPattern,HTTPMETHOD,一条不同操作对应一条授权 Permission )保存到数据库,用户页面可以打开授权,整页面都是 CheckBox 的 Permissions,客户看到那个后自己都晕了,感觉自己蠢了。
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
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
2020-06-19 15:47:56 +08:00
@hantsy 你的权限系统的思路,能说明一下么?
zhaoxixiangban
2020-06-19 15:59:13 +08:00
@skypyb #4 需要前端进行自定义配置角色权限的,类似五楼的需求。- -· 汗 ,所以需要把可配置的权限都给到前端
Vegetable
2020-06-19 16:01:03 +08:00
目测 xy problem
zhaoxixiangban
2020-06-19 16:02:06 +08:00
@siweipancc #7 嗯 现在后台权限这边问题不大,像上面五楼说的类似,需要用户对细粒度的权限进行自定义配置,就需要我们把相应的接口数据都存起来给前端,接口列表数据这部分都是怎么实现的呢?手动加数据库?
zhaoxixiangban
2020-06-19 16:04:36 +08:00
@hantsy #5 对就是这种需求 ,操作接口是自己手动加数据库吗
zhaoxixiangban
2020-06-19 16:05:39 +08:00
@jorneyr #2
@ourslay #6
抱歉是我没有说清楚 ,问题点是五楼阐述的这种状况。
zhaoxixiangban
2020-06-19 16:06:29 +08:00
@admin7785 #1 具体怎么个搞法
siweipancc
2020-06-19 18:20:35 +08:00
@zhaoxixiangban 我建议你不要这么玩,最后双头坑,角色或者组跟模块绑定的设计才能继续维护。
daimubai
2020-06-19 22:11:38 +08:00
手动加数据库,然后加载权限信息到用户,最后配置全局权限控制;
zhenjiachen
2020-06-20 08:31:29 +08:00
看一下我的实现,可能有 bug,不过可以借鉴一下。https://github.com/chenzhenjia/niubi-commons/blob/master/README.md
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
2020-06-20 11:01:39 +08:00
user->permission,user->role>permission 应该都是 n:m 多对多。
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 要灵活配置,说白了一点,从需求角度来分析,就是它自己需求不确定,不知道要做什么东西。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/682953

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX