From cee872000aad8c8247c0f3738602eb2b967628fc Mon Sep 17 00:00:00 2001 From: EightMonth Date: Thu, 29 Feb 2024 17:11:44 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=A4=84=E7=90=86=20#5601=20=EF=BC=8C?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0@ignoreAuth=E6=B3=A8=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/jeecg/config/shiro/IgnoreAuth.java | 16 ++++ .../org/jeecg/config/shiro/ShiroConfig.java | 81 +++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/IgnoreAuth.java diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/IgnoreAuth.java b/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/IgnoreAuth.java new file mode 100644 index 0000000000..15a6de792f --- /dev/null +++ b/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 { +} diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java b/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java index 6a274a62d2..2355988d88 100644 --- a/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java +++ b/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.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.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; @@ -25,11 +29,14 @@ 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 redis.clients.jedis.HostAndPort; import redis.clients.jedis.JedisCluster; import javax.annotation.Resource; import javax.servlet.Filter; +import java.lang.reflect.Method; +import java.time.Duration; import java.util.*; /** @@ -51,6 +58,9 @@ public class ShiroConfig { @Autowired(required = false) private RedisProperties redisProperties; + @Autowired + private ApplicationContext ctx; + /** * Filter Chain定义说明 * @@ -165,6 +175,14 @@ public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) { // 企业微信证书排除 filterChainDefinitionMap.put("/WW_verify*", "anon"); + // 通过注解免登录url + List ignoreAuthUrlList = collectIgnoreAuthUrl(ctx); + if (!CollectionUtils.isEmpty(ignoreAuthUrlList)) { + for (String url : ignoreAuthUrlList) { + filterChainDefinitionMap.put(url, "anon"); + } + } + // 添加自己的过滤器并且取名为jwt Map filterMap = new HashMap(1); //如果cloudServer为空 则说明是单体 需要加载跨域配置【微服务跨域切换】 @@ -303,4 +321,67 @@ public IRedisManager redisManager() { return manager; } + + @SneakyThrows + public List collectIgnoreAuthUrl(ApplicationContext context) { + List ignoreAuthUrls = new ArrayList<>(); + Map controllers = context.getBeansWithAnnotation(RestController.class); + for (Object bean : controllers.values()) { + if (!(bean instanceof Advised)) { + return null; + } + 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 rebuildUrl(String[] bases, String[] uris) { + List 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; + } + } From acf07133859f79ee1a3a823172b16fa32159b775 Mon Sep 17 00:00:00 2001 From: EightMonth Date: Thu, 29 Feb 2024 17:43:56 +0800 Subject: [PATCH 2/2] Update ShiroConfig.java --- .../src/main/java/org/jeecg/config/shiro/ShiroConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java b/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java index 2355988d88..b36700d03d 100644 --- a/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java +++ b/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java @@ -328,7 +328,7 @@ public List collectIgnoreAuthUrl(ApplicationContext context) { Map controllers = context.getBeansWithAnnotation(RestController.class); for (Object bean : controllers.values()) { if (!(bean instanceof Advised)) { - return null; + continue; } Class beanClass = ((Advised) bean).getTargetSource().getTarget().getClass(); RequestMapping base = beanClass.getAnnotation(RequestMapping.class);