Skip to content

Commit 4dda9eb

Browse files
committed
refactor: 优化权限控制
1 parent 3f7e040 commit 4dda9eb

File tree

16 files changed

+332
-134
lines changed

16 files changed

+332
-134
lines changed

hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/Authentication.java

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package org.hswebframework.web.authorization;
1919

20+
import org.hswebframework.web.authorization.annotation.Logical;
2021
import org.springframework.util.StringUtils;
2122
import reactor.core.publisher.Mono;
2223

@@ -93,18 +94,37 @@ static Optional<Authentication> current() {
9394
* @return 用户持有的权限集合
9495
*/
9596
List<Permission> getPermissions();
96-
97+
9798
default boolean hasDimension(String type, String... id) {
98-
return hasDimension(type, Arrays.asList(id));
99+
return hasAnyDimension(type, Arrays.asList(id));
100+
}
101+
102+
default boolean hasAllDimension(String type, Collection<String> id) {
103+
if (id.isEmpty()) {
104+
return !getDimensions(type).isEmpty();
105+
}
106+
return getDimensions(type)
107+
.stream()
108+
.allMatch(p -> id.contains(p.getId()));
109+
}
110+
111+
default boolean hasAnyDimension(String type, Collection<String> id) {
112+
if (id.isEmpty()) {
113+
return !getDimensions(type).isEmpty();
114+
}
115+
return getDimensions(type)
116+
.stream()
117+
.anyMatch(p -> id.contains(p.getId()));
99118
}
100119

120+
@Deprecated
101121
default boolean hasDimension(String type, Collection<String> id) {
102122
if (id.isEmpty()) {
103123
return !getDimensions(type).isEmpty();
104124
}
105125
return getDimensions(type)
106-
.stream()
107-
.anyMatch(p -> id.contains(p.getId()));
126+
.stream()
127+
.anyMatch(p -> id.contains(p.getId()));
108128
}
109129

110130
default boolean hasDimension(DimensionType type, String id) {
@@ -116,19 +136,19 @@ default Optional<Dimension> getDimension(String type, String id) {
116136
return Optional.empty();
117137
}
118138
return getDimensions()
119-
.stream()
120-
.filter(dimension -> dimension.getId().equals(id) && type.equalsIgnoreCase(dimension.getType().getId()))
121-
.findFirst();
139+
.stream()
140+
.filter(dimension -> dimension.getId().equals(id) && type.equalsIgnoreCase(dimension.getType().getId()))
141+
.findFirst();
122142
}
123143

124144
default Optional<Dimension> getDimension(DimensionType type, String id) {
125145
if (type == null) {
126146
return Optional.empty();
127147
}
128148
return getDimensions()
129-
.stream()
130-
.filter(dimension -> dimension.getId().equals(id) && type.isSameType(dimension.getType()))
131-
.findFirst();
149+
.stream()
150+
.filter(dimension -> dimension.getId().equals(id) && type.isSameType(dimension.getType()))
151+
.findFirst();
132152
}
133153

134154

@@ -137,19 +157,19 @@ default List<Dimension> getDimensions(String type) {
137157
return Collections.emptyList();
138158
}
139159
return getDimensions()
140-
.stream()
141-
.filter(dimension -> dimension.getType().isSameType(type))
142-
.collect(Collectors.toList());
160+
.stream()
161+
.filter(dimension -> dimension.getType().isSameType(type))
162+
.collect(Collectors.toList());
143163
}
144164

145165
default List<Dimension> getDimensions(DimensionType type) {
146166
if (type == null) {
147167
return Collections.emptyList();
148168
}
149169
return getDimensions()
150-
.stream()
151-
.filter(dimension -> dimension.getType().isSameType(type))
152-
.collect(Collectors.toList());
170+
.stream()
171+
.filter(dimension -> dimension.getType().isSameType(type))
172+
.collect(Collectors.toList());
153173
}
154174

155175

@@ -164,9 +184,9 @@ default Optional<Permission> getPermission(String id) {
164184
return Optional.empty();
165185
}
166186
return getPermissions()
167-
.stream()
168-
.filter(permission -> permission.getId().equals(id))
169-
.findAny();
187+
.stream()
188+
.filter(permission -> permission.getId().equals(id))
189+
.findAny();
170190
}
171191

172192
/**
@@ -179,8 +199,8 @@ default Optional<Permission> getPermission(String id) {
179199
default boolean hasPermission(String permissionId, String... actions) {
180200
return hasPermission(permissionId,
181201
actions.length == 0
182-
? Collections.emptyList()
183-
: Arrays.asList(actions));
202+
? Collections.emptyList()
203+
: Arrays.asList(actions));
184204
}
185205

186206
default boolean hasPermission(String permissionId, Collection<String> actions) {
@@ -190,8 +210,8 @@ default boolean hasPermission(String permissionId, Collection<String> actions) {
190210
}
191211
if (Objects.equals(permissionId, permission.getId())) {
192212
return actions.isEmpty()
193-
|| permission.getActions().containsAll(actions)
194-
|| permission.getActions().contains("*");
213+
|| permission.getActions().containsAll(actions)
214+
|| permission.getActions().contains("*");
195215
}
196216
}
197217
return false;

hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/AuthenticationPredicate.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ static AuthenticationPredicate has(String permissionString) {
1818
}
1919

2020
static AuthenticationPredicate dimension(String dimension, String... id) {
21-
return autz -> autz.hasDimension(dimension, Arrays.asList(id));
21+
return autz -> autz.hasAnyDimension(dimension, Arrays.asList(id));
2222
}
2323

2424
static AuthenticationPredicate permission(String permissionId, String... actions) {
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,67 @@
11
package org.hswebframework.web.authorization.annotation;
22

3+
import org.hswebframework.web.authorization.DimensionType;
4+
35
import java.lang.annotation.*;
46

7+
import static java.lang.annotation.ElementType.*;
8+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
9+
10+
/**
11+
* 请使用注解继承方式使用此注解
12+
*
13+
* @author zhouhao
14+
* @see RequiresRoles
15+
* @since 4.0
16+
*/
517
@Target({ElementType.ANNOTATION_TYPE})
618
@Retention(RetentionPolicy.RUNTIME)
719
@Inherited
820
@Documented
21+
@Repeatable(value = Dimension.List.class)
922
public @interface Dimension {
1023

24+
/**
25+
* 维度类型标识,如: role,org
26+
*
27+
* @return 维度类型
28+
* @see org.hswebframework.web.authorization.Dimension#getType()
29+
* @see DimensionType#getId()
30+
* @see org.hswebframework.web.authorization.Authentication#hasDimension(String, String...)
31+
*/
1132
String type();
1233

34+
/**
35+
* 具体的维度ID,如: 角色ID,组织ID
36+
*
37+
* @return 维度ID
38+
* @see org.hswebframework.web.authorization.Dimension#getId()
39+
* @see org.hswebframework.web.authorization.Authentication#hasDimension(String, String...)
40+
*/
1341
String[] id() default {};
1442

43+
/**
44+
* 配置了多个ID时的判断逻辑,默认为任意满足则认为有权限.
45+
*
46+
* @return Logical
47+
*/
1548
Logical logical() default Logical.DEFAULT;
1649

50+
/**
51+
* @return 说明
52+
*/
1753
String[] description() default {};
1854

55+
/**
56+
* @return 是否忽略
57+
*/
1958
boolean ignore() default false;
59+
60+
@Target({ANNOTATION_TYPE})
61+
@Retention(RUNTIME)
62+
@Documented
63+
@Inherited
64+
@interface List {
65+
Dimension[] value() default {};
66+
}
2067
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package org.hswebframework.web.authorization.annotation;
2+
3+
import java.lang.annotation.*;
4+
5+
import static java.lang.annotation.ElementType.*;
6+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
7+
8+
/**
9+
* 标记多个维度的权限控制相关配置
10+
*
11+
* @author zhouhao
12+
* @since 5.0.1
13+
*/
14+
@Target({ElementType.METHOD, TYPE, ANNOTATION_TYPE, FIELD})
15+
@Retention(RetentionPolicy.RUNTIME)
16+
@Inherited
17+
@Documented
18+
public @interface Dimensions {
19+
20+
/**
21+
* 存在多个维度时的判断逻辑,默认任意一个满足则认为有权限
22+
*
23+
* @return Logical
24+
*/
25+
Logical logical() default Logical.DEFAULT;
26+
27+
/**
28+
* @return 针对当前配置的说明信息
29+
*/
30+
String[] description() default {};
31+
32+
}

hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/RequiresRoles.java

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,49 @@
55

66
import java.lang.annotation.*;
77

8-
@Target({ElementType.METHOD})
8+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
9+
10+
/**
11+
* 注解根据角色维度进行权限控制,具有权限的用户才可访问对应的方法.
12+
*
13+
* <pre>{@code
14+
* @RequiresRoles("admin")
15+
* public Mono<Void> handleRequest(){
16+
*
17+
* }
18+
* }</pre>
19+
*
20+
* @author zhouhao
21+
* @see Dimension
22+
* @since 4.0
23+
*/
24+
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD})
925
@Retention(RetentionPolicy.RUNTIME)
1026
@Inherited
1127
@Documented
12-
@Dimension(type = "role", description = "控制角色")
28+
@Dimension(type = "role")
29+
@Repeatable(RequiresRoles.List.class)
1330
public @interface RequiresRoles {
1431

32+
/**
33+
* @return 角色ID
34+
*/
1535
@AliasFor(annotation = Dimension.class, attribute = "id")
1636
String[] value() default {};
1737

38+
/**
39+
* 多个角色时的判断逻辑
40+
* @return Logical
41+
*/
1842
@AliasFor(annotation = Dimension.class, attribute = "logical")
1943
Logical logical() default Logical.DEFAULT;
2044

45+
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD})
46+
@Retention(RUNTIME)
47+
@Documented
48+
@Inherited
49+
@Dimension.List()
50+
@interface List {
51+
RequiresRoles[] value();
52+
}
2153
}

hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/Resource.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66

77
import java.lang.annotation.*;
88

9+
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
10+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
11+
912
/**
1013
* 接口资源声明注解,声明Controller的资源相关信息,用于进行权限控制。
1114
* <br>
@@ -53,6 +56,7 @@
5356
@Retention(RetentionPolicy.RUNTIME)
5457
@Inherited
5558
@Documented
59+
@Repeatable(Resource.List.class)
5660
public @interface Resource {
5761

5862
/**
@@ -98,4 +102,12 @@
98102
* @return 是否合并
99103
*/
100104
boolean merge() default true;
105+
106+
@Target({ANNOTATION_TYPE})
107+
@Retention(RUNTIME)
108+
@Documented
109+
@Inherited
110+
@interface List {
111+
Resource[] value();
112+
}
101113
}

hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/DimensionDefinition.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@
66
import org.hswebframework.web.authorization.DimensionType;
77
import org.hswebframework.web.authorization.annotation.Logical;
88
import org.hswebframework.web.bean.FastBeanCopier;
9+
import reactor.function.Predicate3;
910

11+
import java.util.Collection;
12+
import java.util.Collections;
1013
import java.util.HashSet;
1114
import java.util.Set;
15+
import java.util.function.BiPredicate;
16+
import java.util.function.Predicate;
1217

1318
@Getter
1419
@Setter
@@ -23,10 +28,27 @@ public class DimensionDefinition {
2328

2429
private Logical logical = Logical.DEFAULT;
2530

31+
public boolean hasDimension(Predicate3<String,Logical, Set<String>> filter) {
32+
return filter.test(typeId,logical, Collections.unmodifiableSet(dimensionId));
33+
}
34+
35+
public boolean hasDimension(Set<String> dimensionIdPredicate) {
36+
if (logical == Logical.AND) {
37+
return dimensionIdPredicate.containsAll(dimensionId);
38+
}
39+
return dimensionId
40+
.stream()
41+
.anyMatch(dimensionIdPredicate::contains);
42+
}
43+
2644
public boolean hasDimension(String id) {
2745
return dimensionId.contains(id);
2846
}
2947

48+
public void addDimensionI(Set<String> id) {
49+
dimensionId.addAll(id);
50+
}
51+
3052
public DimensionDefinition copy() {
3153
return FastBeanCopier.copy(this, DimensionDefinition::new);
3254
}

0 commit comments

Comments
 (0)