Jelajahi Sumber

增加权限判断工具

zhouhao 7 tahun lalu
induk
melakukan
28e39255ba

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

@@ -0,0 +1,49 @@
+package org.hswebframework.web.authorization;
+
+import java.util.Objects;
+import java.util.function.Predicate;
+
+/**
+ * @author zhouhao
+ * @since 3.0
+ */
+public interface AuthenticationPredicate extends Predicate<Authentication> {
+
+    static AuthenticationPredicate has(String permissionString) {
+        return AuthenticationUtils.createPredicate(permissionString);
+    }
+
+    static AuthenticationPredicate role(String role) {
+        return autz -> autz.hasRole(role);
+    }
+
+    static AuthenticationPredicate permission(String permissionId, String... actions) {
+        return autz -> autz.hasPermission(permissionId, actions);
+    }
+
+    default AuthenticationPredicate and(String permissionString) {
+        return and(has(permissionString));
+    }
+
+    default AuthenticationPredicate or(String permissionString) {
+        return or(has(permissionString));
+    }
+
+    @Override
+    default AuthenticationPredicate and(Predicate<? super Authentication> other) {
+        Objects.requireNonNull(other);
+        return (t) -> test(t) && other.test(t);
+    }
+
+    @Override
+    default AuthenticationPredicate or(Predicate<? super Authentication> other) {
+        Objects.requireNonNull(other);
+        return (t) -> test(t) || other.test(t);
+    }
+
+    default boolean test() {
+        return Authentication.current()
+                .map(this::test)
+                .orElse(false);
+    }
+}

+ 50 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/AuthenticationUtils.java

@@ -0,0 +1,50 @@
+package org.hswebframework.web.authorization;
+
+import org.springframework.util.StringUtils;
+
+/**
+ * @author zhouhao
+ * @since 3.0
+ */
+public class AuthenticationUtils {
+
+    public static AuthenticationPredicate createPredicate(String expression) {
+        if (StringUtils.isEmpty(expression)) {
+            return (authentication -> false);
+        }
+        AuthenticationPredicate main = null;
+        // permission:user:add or update
+        AuthenticationPredicate temp = null;
+        boolean lastAnd = true;
+        for (String conf : expression.split("[ ]")) {
+            if (conf.startsWith("permission:")) {
+                String[] permissionAndActions = conf.split("[:]", 2);
+                if (permissionAndActions.length < 2) {
+                    temp = authentication -> !authentication.getPermissions().isEmpty();
+                } else {
+                    String[] real = permissionAndActions[1].split("[:]");
+                    temp = real.length > 1 ?
+                            AuthenticationPredicate.permission(real[0], real[1].split("[,]"))
+                            : AuthenticationPredicate.permission(real[0]);
+                }
+            } else if (conf.startsWith("role")) {
+                String[] real = conf.split("[:]", 2);
+                if (real.length < 2) {
+                    temp = authentication -> !authentication.getRoles().isEmpty();
+                } else {
+                    temp = AuthenticationPredicate.role(real[1]);
+                }
+            } else if (main != null && conf.equalsIgnoreCase("and")) {
+                lastAnd = true;
+                main = main.and(temp);
+            } else if (main != null && conf.equalsIgnoreCase("or")) {
+                main = main.or(temp);
+                lastAnd = false;
+            }
+            if (main == null) {
+                main = temp;
+            }
+        }
+        return main == null ? a -> false : (lastAnd ? main.and(temp) : main.or(temp));
+    }
+}

+ 6 - 1
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/DefaultUserTokenManager.java

@@ -32,6 +32,7 @@ import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.function.Consumer;
+import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
 /**
@@ -242,6 +243,7 @@ public class DefaultUserTokenManager implements UserTokenManager {
         if (mode == AllopatricLoginMode.deny) {
             boolean hasAnotherToken = getByUserId(userId)
                     .stream()
+                    .filter(userToken -> type.equals(userToken.getType()))
                     .map(SimpleUserToken.class::cast)
                     .peek(this::checkTimeout)
                     .anyMatch(UserToken::isEffective);
@@ -252,7 +254,10 @@ public class DefaultUserTokenManager implements UserTokenManager {
             //将在其他地方登录的用户设置为离线
             List<UserToken> oldToken = getByUserId(userId);
             for (UserToken userToken : oldToken) {
-                changeTokenState(userToken.getToken(), TokenState.offline);
+                //相同的tokenType才让其下线
+                if (type.equals(userToken.getType())) {
+                    changeTokenState(userToken.getToken(), TokenState.offline);
+                }
             }
         }
         detail.setState(TokenState.effective);

+ 2 - 0
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/token/UserTokenManager.java

@@ -20,6 +20,7 @@ package org.hswebframework.web.authorization.token;
 
 import java.util.List;
 import java.util.function.Consumer;
+import java.util.function.Predicate;
 
 /**
  * 用户令牌管理器,用于管理用户令牌
@@ -137,4 +138,5 @@ public interface UserTokenManager {
      * @see this#signOutByToken(String)
      */
     void checkExpiredToken();
+
 }

+ 18 - 0
hsweb-authorization/hsweb-authorization-api/src/test/java/org/hswebframework/web/authorization/AuthenticationTests.java

@@ -64,6 +64,24 @@ public class AuthenticationTests {
         assertTrue(authentication.hasPermission("user-manager", "get"));
         assertTrue(!authentication.hasPermission("user-manager", "delete"));
 
+        boolean has = AuthenticationPredicate.has("permission:user-manager")
+                .or(AuthenticationPredicate.role("admin-role"))
+                .test(authentication);
+
+        Assert.assertTrue(has);
+        has = AuthenticationPredicate.has("permission:user-manager:test")
+                .and(AuthenticationPredicate.role("admin-role"))
+                .test(authentication);
+        Assert.assertFalse(has);
+
+        has = AuthenticationPredicate.has("permission:user-manager:get and role:admin-role")
+                .test(authentication);
+        Assert.assertTrue(has);
+
+        has = AuthenticationPredicate.has("permission:user-manager:test or role:admin-role")
+                .test(authentication);
+        Assert.assertTrue(has);
+
         //获取数据权限配置
         Set<String> fields = authentication.getPermission("user-manager")
                 .map(permission -> permission.findDenyFields(Permission.ACTION_QUERY))