diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/Authentication.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/Authentication.java
index 976909412..ebb5b5b3d 100644
--- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/Authentication.java
+++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/Authentication.java
@@ -30,6 +30,7 @@ import java.util.stream.Collectors;
*
* - springmvc 入参方式: ResponseMessage myTest(Authorization auth){}
* - 静态方法方式:AuthorizationHolder.get();
+ * - 响应式方式: return Authentication.currentReactive().map(auth->....)
*
*
* @author zhouhao
@@ -51,6 +52,7 @@ public interface Authentication extends Serializable {
*
* @return 当前用户权限信息
* @see ReactiveAuthenticationHolder
+ * @since 4.0
*/
static Mono currentReactive() {
return ReactiveAuthenticationHolder.get();
@@ -81,6 +83,7 @@ public interface Authentication extends Serializable {
/**
* @return 用户所有维度
+ * @since 4.0
*/
List getDimensions();
@@ -196,6 +199,12 @@ public interface Authentication extends Serializable {
*/
Map getAttributes();
+ /**
+ * 合并权限
+ *
+ * @param source 源权限信息
+ * @return 合并后的信息
+ */
Authentication merge(Authentication source);
}
diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/ReactiveAuthenticationHolder.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/ReactiveAuthenticationHolder.java
index e1f929712..bd8dfa038 100644
--- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/ReactiveAuthenticationHolder.java
+++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/ReactiveAuthenticationHolder.java
@@ -42,7 +42,7 @@ import java.util.stream.Collectors;
*
* @author zhouhao
* @see ReactiveAuthenticationSupplier
- * @since 3.0
+ * @since 4.0
*/
public final class ReactiveAuthenticationHolder {
private static final List suppliers = new ArrayList<>();
@@ -90,4 +90,14 @@ public final class ReactiveAuthenticationHolder {
}
}
+ public static void setSupplier(ReactiveAuthenticationSupplier supplier){
+ lock.writeLock().lock();
+ try {
+ suppliers.clear();
+ suppliers.add(supplier);
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
}
diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/DataAccessType.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/DataAccessType.java
index 33d8bc093..675e3d911 100644
--- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/DataAccessType.java
+++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/DataAccessType.java
@@ -24,4 +24,5 @@ public @interface DataAccessType {
Class extends DataAccessConfiguration> configuration() default DataAccessConfiguration.class;
+ boolean ignore() default false;
}
\ No newline at end of file
diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/DimensionDataAccess.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/DimensionDataAccess.java
index fe4e4f0bd..6a90247b2 100644
--- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/DimensionDataAccess.java
+++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/DimensionDataAccess.java
@@ -15,7 +15,10 @@ public @interface DimensionDataAccess {
Mapping[] mapping() default {};
@AliasFor(annotation = Authorize.class)
- Phased phased() default Phased.before;
+ Phased phased() default Phased.before;
+
+ @AliasFor(annotation = DataAccessType.class)
+ boolean ignore() default false;
@Retention(RetentionPolicy.RUNTIME)
@Documented
diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/FieldDataAccess.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/FieldDataAccess.java
index cc194004d..5c945f3fc 100644
--- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/FieldDataAccess.java
+++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/FieldDataAccess.java
@@ -1,11 +1,15 @@
package org.hswebframework.web.authorization.annotation;
+import org.springframework.core.annotation.AliasFor;
+
import java.lang.annotation.*;
-@DataAccessType(id = "DENY_FIELDS", name = "字段权限")
+@DataAccessType(id = "FIELD_DENY", name = "字段权限")
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
public @interface FieldDataAccess {
+ @AliasFor(annotation = DataAccessType.class)
+ boolean ignore() default false;
}
diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/UserOwnData.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/UserOwnData.java
index ad6e4235a..7f4caa9f8 100644
--- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/UserOwnData.java
+++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/annotation/UserOwnData.java
@@ -9,7 +9,6 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
-@DataAccess
@DataAccessType(id = "user_own_data", name = "用户自己的数据")
public @interface UserOwnData {
diff --git a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/DataAccessDefinition.java b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/DataAccessDefinition.java
index 7281b0937..f30135276 100644
--- a/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/DataAccessDefinition.java
+++ b/hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/define/DataAccessDefinition.java
@@ -9,12 +9,12 @@ import java.util.*;
@Setter
public class DataAccessDefinition {
- Set dataAccessTypes=new HashSet<>();
+ Set dataAccessTypes = new HashSet<>();
- public Optional getType(String typeId){
+ public Optional getType(String typeId) {
return dataAccessTypes
.stream()
- .filter(type->type.getId().equalsIgnoreCase(typeId))
+ .filter(type -> type.getId() != null && type.getId().equalsIgnoreCase(typeId))
.findAny();
}
}
diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/AopAuthorizeDefinitionParser.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/AopAuthorizeDefinitionParser.java
new file mode 100644
index 000000000..db3aa39f1
--- /dev/null
+++ b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/AopAuthorizeDefinitionParser.java
@@ -0,0 +1,155 @@
+package org.hswebframework.web.authorization.basic.define;
+
+import org.hswebframework.web.authorization.annotation.*;
+import org.hswebframework.web.authorization.define.AopAuthorizeDefinition;
+import org.hswebframework.web.authorization.define.ResourceActionDefinition;
+import org.hswebframework.web.authorization.define.ResourceDefinition;
+import org.springframework.core.annotation.AnnotatedElementUtils;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class AopAuthorizeDefinitionParser {
+
+ private static final Set> types = new HashSet<>(Arrays.asList(
+ Authorize.class,
+ DataAccess.class,
+ Dimension.class,
+ Resource.class,
+ ResourceAction.class,
+ DataAccessType.class
+ ));
+
+ private Set methodAnnotation;
+
+ private Set classAnnotation;
+
+ private Map, List> classAnnotationGroup;
+
+ private Map, List> methodAnnotationGroup;
+
+ private DefaultBasicAuthorizeDefinition definition;
+
+ AopAuthorizeDefinitionParser(Class> targetClass, Method method) {
+ definition = new DefaultBasicAuthorizeDefinition();
+ definition.setTargetClass(targetClass);
+ definition.setTargetMethod(method);
+
+ methodAnnotation = AnnotatedElementUtils.findAllMergedAnnotations(method, types);
+
+ classAnnotation = AnnotatedElementUtils.findAllMergedAnnotations(targetClass, types);
+
+ classAnnotationGroup = classAnnotation
+ .stream()
+ .collect(Collectors.groupingBy(Annotation::annotationType));
+
+ methodAnnotationGroup = methodAnnotation
+ .stream()
+ .collect(Collectors.groupingBy(Annotation::annotationType));
+ }
+
+ private void initClassAnnotation() {
+ for (Annotation annotation : classAnnotation) {
+ if (annotation instanceof Authorize) {
+ definition.putAnnotation(((Authorize) annotation));
+ }
+ if (annotation instanceof Resource) {
+ definition.putAnnotation(((Resource) annotation));
+ }
+ }
+ }
+
+ private void initMethodAnnotation() {
+ for (Annotation annotation : methodAnnotation) {
+ if (annotation instanceof Authorize) {
+ definition.putAnnotation(((Authorize) annotation));
+ }
+ if (annotation instanceof Resource) {
+ definition.putAnnotation(((Resource) annotation));
+ }
+ if (annotation instanceof Dimension) {
+ definition.putAnnotation(((Dimension) annotation));
+ }
+ }
+ }
+
+ private void initClassDataAccessAnnotation(){
+ for (Annotation annotation : classAnnotation) {
+ if (annotation instanceof DataAccessType ||
+ annotation instanceof DataAccess) {
+ for (ResourceDefinition resource : definition.getResources().getResources()) {
+ for (ResourceActionDefinition action : resource.getActions()) {
+ if (annotation instanceof DataAccessType) {
+ definition.putAnnotation(action, (DataAccessType) annotation);
+ } else {
+ definition.putAnnotation(action, (DataAccess) annotation);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void initMethodDataAccessAnnotation() {
+ for (Annotation annotation : methodAnnotation) {
+
+ if (annotation instanceof ResourceAction) {
+ getAnnotationByType(Resource.class)
+ .map(res -> definition.getResources().getResource(res.id()).orElse(null))
+ .filter(Objects::nonNull)
+ .forEach(res -> {
+ ResourceAction ra = (ResourceAction) annotation;
+ ResourceActionDefinition action = definition.putAnnotation(res, ra);
+ getAnnotationByType(DataAccessType.class)
+ .findFirst()
+ .ifPresent(dat -> definition.putAnnotation(action, dat));
+ });
+ }
+ Optional actionDefinition = getAnnotationByType(Resource.class)
+ .map(res -> definition.getResources().getResource(res.id()).orElse(null))
+ .filter(Objects::nonNull)
+ .flatMap(res -> getAnnotationByType(ResourceAction.class)
+ .map(ra -> res.getAction(ra.id())
+ .orElse(null))
+ )
+ .filter(Objects::nonNull)
+ .findFirst();
+
+ if (annotation instanceof DataAccessType) {
+ actionDefinition.ifPresent(ra -> definition.putAnnotation(ra, (DataAccessType) annotation));
+ }
+
+ if (annotation instanceof DataAccess) {
+ actionDefinition.ifPresent(ra -> {
+ definition.putAnnotation(ra, (DataAccess) annotation);
+ getAnnotationByType(DataAccessType.class)
+ .findFirst()
+ .ifPresent(dat -> definition.putAnnotation(ra, dat));
+ });
+ }
+
+ }
+ }
+
+ AopAuthorizeDefinition parse() {
+ initClassAnnotation();
+ initClassDataAccessAnnotation();
+ initMethodAnnotation();
+ initMethodDataAccessAnnotation();
+
+ return definition;
+ }
+
+
+ private Stream getAnnotationByType(Class type) {
+ return Optional.ofNullable(methodAnnotationGroup.getOrDefault(type, classAnnotationGroup.get(type)))
+ .map(Collection::stream)
+ .orElseGet(Stream::empty)
+ .map(type::cast);
+ }
+
+}
diff --git a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinition.java b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinition.java
index 3564361de..d667a4d0d 100644
--- a/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinition.java
+++ b/hsweb-authorization/hsweb-authorization-basic/src/main/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinition.java
@@ -5,12 +5,14 @@ import lombok.*;
import org.hswebframework.web.authorization.annotation.*;
import org.hswebframework.web.authorization.define.*;
import org.springframework.core.annotation.AnnotatedElementUtils;
+import org.springframework.util.StringUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
/**
* 默认权限权限定义
@@ -54,99 +56,7 @@ public class DefaultBasicAuthorizeDefinition implements AopAuthorizeDefinition {
));
public static AopAuthorizeDefinition from(Class targetClass, Method method) {
- DefaultBasicAuthorizeDefinition definition = new DefaultBasicAuthorizeDefinition();
- definition.setTargetClass(targetClass);
- definition.setTargetMethod(method);
-
- Set methodAnnotation = AnnotatedElementUtils.findAllMergedAnnotations(method, types);
-
- Set classAnnotation = AnnotatedElementUtils.findAllMergedAnnotations(targetClass, types);
-
- Map classAnnotationMap = classAnnotation
- .stream()
- .collect(Collectors.toMap(Annotation::annotationType, Function.identity()));
-
- Map mapping = methodAnnotation
- .stream()
- .collect(Collectors.toMap(Annotation::annotationType, Function.identity()));
-
- for (Annotation annotation : classAnnotation) {
- if (annotation instanceof Authorize) {
- definition.putAnnotation(((Authorize) annotation));
- }
- if (annotation instanceof Resource) {
- definition.putAnnotation(((Resource) annotation));
- }
- }
-
- for (Annotation annotation : methodAnnotation) {
- if (annotation instanceof Authorize) {
- definition.putAnnotation(((Authorize) annotation));
- }
- if (annotation instanceof Resource) {
- definition.putAnnotation(((Resource) annotation));
- }
- if (annotation instanceof Dimension) {
- definition.putAnnotation(((Dimension) annotation));
- }
- }
-
- for (Annotation annotation : methodAnnotation) {
-
- if (annotation instanceof ResourceAction) {
- Optional.ofNullable(mapping.getOrDefault(Resource.class, classAnnotationMap.get(Resource.class)))
- .map(Resource.class::cast)
- .flatMap(res -> definition.getResources().getResource(res.id()))
- .ifPresent(res -> {
-
- ResourceAction ra = (ResourceAction) annotation;
- ResourceActionDefinition action = definition.putAnnotation(res, ra);
-
- Optional.ofNullable(mapping.get(DataAccessType.class))
- .map(DataAccessType.class::cast)
- .ifPresent(dat -> definition.putAnnotation(action, dat));
- });
- }
- Optional actionDefinition = Optional.ofNullable(mapping.getOrDefault(Resource.class, classAnnotationMap.get(Resource.class)))
- .map(Resource.class::cast)
- .flatMap(res -> definition.getResources().getResource(res.id()))
- .flatMap(res -> Optional.ofNullable(mapping.get(ResourceAction.class))
- .map(ResourceAction.class::cast)
- .flatMap(ra -> res.getAction(ra.id())));
-
- if (annotation instanceof DataAccessType) {
- actionDefinition.ifPresent(ra -> definition.putAnnotation(ra, (DataAccessType) annotation));
- }
-
- if (annotation instanceof DataAccess) {
- actionDefinition.ifPresent(ra -> {
- definition.putAnnotation(ra, (DataAccess) annotation);
- Optional.ofNullable(mapping.get(DataAccessType.class))
- .map(DataAccessType.class::cast)
- .ifPresent(dat -> definition.putAnnotation(ra, dat));
- });
- }
-
- }
-
-
- for (Annotation annotation : classAnnotation) {
- if (annotation instanceof DataAccessType||
- annotation instanceof DataAccess) {
- for (ResourceDefinition resource : definition.getResources().getResources()) {
- for (ResourceActionDefinition action : resource.getActions()) {
- if(annotation instanceof DataAccessType) {
- definition.putAnnotation(action, (DataAccessType) annotation);
- }else{
- definition.putAnnotation(action, (DataAccess) annotation);
- }
- }
- }
- }
- }
-
-
- return definition;
+ return new AopAuthorizeDefinitionParser(targetClass,method).parse();
}
public void putAnnotation(Authorize ann) {
@@ -208,18 +118,27 @@ public class DefaultBasicAuthorizeDefinition implements AopAuthorizeDefinition {
}
DataAccessTypeDefinition typeDefinition = new DataAccessTypeDefinition();
for (DataAccessType dataAccessType : ann.type()) {
+ if(dataAccessType.ignore()){
+ continue;
+ }
typeDefinition.setId(dataAccessType.id());
typeDefinition.setName(dataAccessType.name());
typeDefinition.setController(dataAccessType.controller());
typeDefinition.setConfiguration(dataAccessType.configuration());
typeDefinition.setDescription(String.join("\n", dataAccessType.description()));
}
+ if(StringUtils.isEmpty(typeDefinition.getId())){
+ return;
+ }
definition.getDataAccess()
.getDataAccessTypes()
.add(typeDefinition);
}
public void putAnnotation(ResourceActionDefinition definition, DataAccessType dataAccessType) {
+ if(dataAccessType.ignore()){
+ return;
+ }
DataAccessTypeDefinition typeDefinition = new DataAccessTypeDefinition();
typeDefinition.setId(dataAccessType.id());
typeDefinition.setName(dataAccessType.name());
diff --git a/hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/aop/AopAuthorizingControllerTest.java b/hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/aop/AopAuthorizingControllerTest.java
index a75ac701b..31ed54700 100644
--- a/hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/aop/AopAuthorizingControllerTest.java
+++ b/hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/aop/AopAuthorizingControllerTest.java
@@ -10,6 +10,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
@@ -32,7 +33,7 @@ public class AopAuthorizingControllerTest {
authentication.setUser(SimpleUser.builder().id("test").username("test").build());
// authentication.setPermissions(Arrays.asList(SimplePermission.builder().id("test").build()));
authentication.setPermissions(Collections.emptyList());
- ReactiveAuthenticationHolder.addSupplier(new ReactiveAuthenticationSupplier() {
+ ReactiveAuthenticationHolder.setSupplier(new ReactiveAuthenticationSupplier() {
@Override
public Mono get(String userId) {
return Mono.empty();
@@ -73,7 +74,7 @@ public class AopAuthorizingControllerTest {
.dataAccesses(Collections.singleton(config))
.id("test").build()));
- ReactiveAuthenticationHolder.addSupplier(new ReactiveAuthenticationSupplier() {
+ ReactiveAuthenticationHolder.setSupplier(new ReactiveAuthenticationSupplier() {
@Override
public Mono get(String userId) {
return Mono.empty();
@@ -109,7 +110,7 @@ public class AopAuthorizingControllerTest {
DimensionDataAccessConfig config2 = new DimensionDataAccessConfig();
config2.setAction("save");
config2.setScopeType("role");
- ReactiveAuthenticationHolder.addSupplier(new ReactiveAuthenticationSupplier() {
+ ReactiveAuthenticationHolder.setSupplier(new ReactiveAuthenticationSupplier() {
@Override
public Mono get(String userId) {
return Mono.empty();
diff --git a/hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/aop/TestController.java b/hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/aop/TestController.java
index 880eaed5f..601790a8b 100644
--- a/hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/aop/TestController.java
+++ b/hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/aop/TestController.java
@@ -33,6 +33,7 @@ public class TestController implements ReactiveCrudController queryUser(QueryParam queryParam) {
return Mono.just(queryParam);
}
diff --git a/hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinitionTest.java b/hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinitionTest.java
index 24953d3a6..54d6bf245 100644
--- a/hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinitionTest.java
+++ b/hsweb-authorization/hsweb-authorization-basic/src/test/java/org/hswebframework/web/authorization/basic/define/DefaultBasicAuthorizeDefinitionTest.java
@@ -26,7 +26,7 @@ public class DefaultBasicAuthorizeDefinitionTest {
Assert.assertTrue(resource.hasAction(Arrays.asList("add")));
Assert.assertTrue(resource.getAction("add")
- .map(act->act.getDataAccess().getType("user_own"))
+ .map(act->act.getDataAccess().getType("user_own_data"))
.isPresent());
}