Bläddra i källkod

优化防火墙处理逻辑;

Woody 1 månad sedan
förälder
incheckning
9c6a0c7ed4

+ 10 - 2
framework-security/src/main/java/com/chelvc/framework/security/config/SecurityConfigurer.java

@@ -11,6 +11,8 @@ import com.chelvc.framework.security.crypto.CacheableSecurityCipherHandler;
 import com.chelvc.framework.security.crypto.DefaultSecurityCipherHandler;
 import com.chelvc.framework.security.crypto.SecurityCipherHandler;
 import com.chelvc.framework.security.firewall.Action;
+import com.chelvc.framework.security.firewall.ActionExecutor;
+import com.chelvc.framework.security.firewall.DefaultActionExecutor;
 import com.chelvc.framework.security.firewall.DefaultFirewallProcessor;
 import com.chelvc.framework.security.firewall.FirewallProcessor;
 import com.chelvc.framework.security.interceptor.MethodSecurityExpression;
@@ -125,10 +127,16 @@ public class SecurityConfigurer extends GlobalMethodSecurityConfiguration implem
         return new ContextVariableParser();
     }
 
+    @Bean
+    @ConditionalOnMissingBean(ActionExecutor.class)
+    public ActionExecutor actionExecutor(List<Action> actions) {
+        return new DefaultActionExecutor(actions);
+    }
+
     @Bean
     @ConditionalOnMissingBean(FirewallProcessor.class)
-    public FirewallProcessor firewallProcessor(VariableParser parser, List<Action> actions) {
-        return new DefaultFirewallProcessor(parser, actions);
+    public FirewallProcessor firewallProcessor(VariableParser parser, ActionExecutor executor) {
+        return new DefaultFirewallProcessor(parser, executor);
     }
 
     @Bean

+ 9 - 0
framework-security/src/main/java/com/chelvc/framework/security/firewall/Action.java

@@ -21,4 +21,13 @@ public interface Action {
      * @param rule      匹配规则
      */
     void execute(String principal, Rule rule);
+
+    /**
+     * 动作执行完成
+     *
+     * @param principal 主体信息
+     * @param rule      匹配规则
+     */
+    default void complete(String principal, Rule rule) {
+    }
 }

+ 17 - 0
framework-security/src/main/java/com/chelvc/framework/security/firewall/ActionExecutor.java

@@ -0,0 +1,17 @@
+package com.chelvc.framework.security.firewall;
+
+/**
+ * 动作执行器接口
+ *
+ * @author Woody
+ * @date 2025/3/15
+ */
+public interface ActionExecutor {
+    /**
+     * 执行动作
+     *
+     * @param principal 主体信息
+     * @param rule      匹配规则
+     */
+    void execute(String principal, Rule rule);
+}

+ 53 - 0
framework-security/src/main/java/com/chelvc/framework/security/firewall/DefaultActionExecutor.java

@@ -0,0 +1,53 @@
+package com.chelvc.framework.security.firewall;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+import com.chelvc.framework.common.util.ObjectUtils;
+import com.google.common.collect.Lists;
+import lombok.NonNull;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 动作执行器默认实现
+ *
+ * @author Woody
+ * @date 2025/3/15
+ */
+@Slf4j
+public class DefaultActionExecutor implements ActionExecutor {
+    protected final List<Action> actions;
+
+    public DefaultActionExecutor(@NonNull List<Action> actions) {
+        this.actions = Collections.unmodifiableList(actions);
+    }
+
+    @Override
+    public void execute(String principal, Rule rule) {
+        List<Action> matches = null;
+        try {
+            for (Action action : this.actions) {
+                if (Objects.equals(rule.getAction(), action.getName())) {
+                    if (matches == null) {
+                        matches = Lists.newLinkedList();
+                    }
+                    matches.add(action);
+                    action.execute(principal, rule);
+                }
+            }
+        } finally {
+            if (ObjectUtils.isEmpty(matches)) {
+                log.warn("Firewall action not found: {}, {}", principal, rule.getAction());
+            } else {
+                for (Action action : matches) {
+                    try {
+                        action.complete(principal, rule);
+                    } catch (Exception e) {
+                        log.error("Firewall action complete failed: {}, {}", principal, action.getName(), e);
+                    }
+                }
+            }
+        }
+    }
+}

+ 5 - 19
framework-security/src/main/java/com/chelvc/framework/security/firewall/DefaultFirewallProcessor.java

@@ -30,12 +30,12 @@ import org.springframework.data.redis.core.SessionCallback;
 @Slf4j
 public class DefaultFirewallProcessor implements FirewallProcessor {
     private final VariableParser parser;
-    private final List<Action> actions;
+    private final ActionExecutor executor;
     private volatile IdentityUtils.Generator sequenceGenerator;
 
-    public DefaultFirewallProcessor(@NonNull VariableParser parser, @NonNull List<Action> actions) {
+    public DefaultFirewallProcessor(@NonNull VariableParser parser, @NonNull ActionExecutor executor) {
         this.parser = parser;
-        this.actions = Collections.unmodifiableList(actions);
+        this.executor = executor;
     }
 
     /**
@@ -54,20 +54,6 @@ public class DefaultFirewallProcessor implements FirewallProcessor {
         return this.sequenceGenerator.next();
     }
 
-    /**
-     * 处理规则动作
-     *
-     * @param principal 主体信息
-     * @param rule      匹配规则
-     */
-    private void doAction(String principal, Rule rule) {
-        for (Action action : this.actions) {
-            if (Objects.equals(rule.getAction(), action.getName())) {
-                action.execute(principal, rule);
-            }
-        }
-    }
-
     /**
      * 获取匹配规则
      *
@@ -180,7 +166,7 @@ public class DefaultFirewallProcessor implements FirewallProcessor {
                 if (pair.getValue().getCount() > 0) {
                     return false;
                 }
-                this.doAction(pair.getKey(), pair.getValue());
+                this.executor.execute(pair.getKey(), pair.getValue());
                 return true;
             });
         }
@@ -200,7 +186,7 @@ public class DefaultFirewallProcessor implements FirewallProcessor {
         for (int i = 0, size = actions.size(); i < size && iterator.hasNext(); i++) {
             Pair<String, Rule> pair = iterator.next();
             if (StringUtils.notEmpty(actions.get(i++))) {
-                this.doAction(pair.getKey(), pair.getValue());
+                this.executor.execute(pair.getKey(), pair.getValue());
                 iterator.remove();
             }
         }