Browse Source

Merge pull request #5930 from EightMonth/master

处理 #5601 ,添加@ignoreAuth注解
JEECG 1 year ago
parent
commit
685b81e5ec

+ 16 - 0
jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/IgnoreAuth.java

@@ -0,0 +1,16 @@
+package org.jeecg.config.shiro;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 免认证注解,认证系统结合spring MVC的@RequestMapping获取请求路径进行免登录配置
+ * @author eightmonth@qq.com
+ * @date 2024/2/28 9:58
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface IgnoreAuth {
+}

+ 81 - 1
jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java

@@ -1,5 +1,6 @@
 package org.jeecg.config.shiro;
 
+import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
 import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
@@ -15,8 +16,11 @@ import org.jeecg.common.util.oConvertUtils;
 import org.jeecg.config.JeecgBaseConfig;
 import org.jeecg.config.shiro.filters.CustomShiroFilterFactoryBean;
 import org.jeecg.config.shiro.filters.JwtFilter;
+import org.springframework.aop.framework.Advised;
 import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.boot.web.servlet.FilterRegistrationBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -26,6 +30,7 @@ import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactor
 import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.*;
 import org.springframework.web.filter.DelegatingFilterProxy;
 import redis.clients.jedis.HostAndPort;
 import redis.clients.jedis.JedisCluster;
@@ -33,6 +38,8 @@ import redis.clients.jedis.JedisCluster;
 import javax.annotation.Resource;
 import javax.servlet.DispatcherType;
 import javax.servlet.Filter;
+import java.lang.reflect.Method;
+import java.time.Duration;
 import java.util.*;
 
 /**
@@ -53,7 +60,9 @@ public class ShiroConfig {
     private JeecgBaseConfig jeecgBaseConfig;
     @Autowired(required = false)
     private RedisProperties redisProperties;
-    
+
+    @Autowired
+    private ApplicationContext ctx;
     /**
      * Filter Chain定义说明
      *
@@ -168,6 +177,14 @@ public class ShiroConfig {
         // 企业微信证书排除
         filterChainDefinitionMap.put("/WW_verify*", "anon");
 
+        // 通过注解免登录url
+        List<String> ignoreAuthUrlList = collectIgnoreAuthUrl(ctx);
+        if (!CollectionUtils.isEmpty(ignoreAuthUrlList)) {
+            for (String url : ignoreAuthUrlList) {
+                filterChainDefinitionMap.put(url, "anon");
+            }
+        }
+
         // 添加自己的过滤器并且取名为jwt
         Map<String, Filter> filterMap = new HashMap<String, Filter>(1);
         //如果cloudServer为空 则说明是单体 需要加载跨域配置【微服务跨域切换】
@@ -320,4 +337,67 @@ public class ShiroConfig {
         return manager;
     }
 
+
+    @SneakyThrows
+    public List<String> collectIgnoreAuthUrl(ApplicationContext context) {
+        List<String> ignoreAuthUrls = new ArrayList<>();
+        Map<String, Object> controllers = context.getBeansWithAnnotation(RestController.class);
+        for (Object bean : controllers.values()) {
+            if (!(bean instanceof Advised)) {
+                continue;
+            }
+            Class<?> beanClass = ((Advised) bean).getTargetSource().getTarget().getClass();
+            RequestMapping base = beanClass.getAnnotation(RequestMapping.class);
+            String[] baseUrl = {};
+            if (Objects.nonNull(base)) {
+                baseUrl = base.value();
+            }
+            Method[] methods = beanClass.getDeclaredMethods();
+
+            for (Method method : methods) {
+                if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(RequestMapping.class)) {
+                    RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
+                    String[] uri = requestMapping.value();
+                    ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
+                } else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(GetMapping.class)) {
+                    GetMapping requestMapping = method.getAnnotation(GetMapping.class);
+                    String[] uri = requestMapping.value();
+                    ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
+                } else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(PostMapping.class)) {
+                    PostMapping requestMapping = method.getAnnotation(PostMapping.class);
+                    String[] uri = requestMapping.value();
+                    ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
+                } else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(PutMapping.class)) {
+                    PutMapping requestMapping = method.getAnnotation(PutMapping.class);
+                    String[] uri = requestMapping.value();
+                    ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
+                } else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(DeleteMapping.class)) {
+                    DeleteMapping requestMapping = method.getAnnotation(DeleteMapping.class);
+                    String[] uri = requestMapping.value();
+                    ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
+                } else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(PatchMapping.class)) {
+                    PatchMapping requestMapping = method.getAnnotation(PatchMapping.class);
+                    String[] uri = requestMapping.value();
+                    ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
+                }
+            }
+        }
+
+        return ignoreAuthUrls;
+    }
+
+    private List<String> rebuildUrl(String[] bases, String[] uris) {
+        List<String> urls = new ArrayList<>();
+        for (String base : bases) {
+            for (String uri : uris) {
+                urls.add(prefix(base)+prefix(uri));
+            }
+        }
+        return urls;
+    }
+
+    private String prefix(String seg) {
+        return seg.startsWith("/") ? seg : "/"+seg;
+    }
+
 }