diff --git a/eladmin/eladmin-common/src/main/java/me/zhengjie/config/webmvc/SwaggerConfig.java b/eladmin/eladmin-common/src/main/java/me/zhengjie/config/webmvc/SwaggerConfig.java index 90b5815..19bf102 100644 --- a/eladmin/eladmin-common/src/main/java/me/zhengjie/config/webmvc/SwaggerConfig.java +++ b/eladmin/eladmin-common/src/main/java/me/zhengjie/config/webmvc/SwaggerConfig.java @@ -15,7 +15,11 @@ */ package me.zhengjie.config.webmvc; +import lombok.RequiredArgsConstructor; +import me.zhengjie.utils.AnonTagUtils; +import me.zhengjie.utils.StringUtils; import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; @@ -31,6 +35,9 @@ import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; import java.util.ArrayList; import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; +import java.util.stream.Collectors; /** * api页面 /doc.html @@ -39,14 +46,20 @@ import java.util.List; */ @Configuration @EnableSwagger2 +@RequiredArgsConstructor public class SwaggerConfig { + @Value("${server.servlet.context-path:}") + private String apiPath; + @Value("${jwt.header}") private String tokenHeader; @Value("${swagger.enabled}") private Boolean enabled; + private final ApplicationContext applicationContext; + @Bean @SuppressWarnings("all") public Docket createRestApi() { @@ -87,10 +100,14 @@ public class SwaggerConfig { } private SecurityContext getContextByPath() { + Set urls = AnonTagUtils.getAllAnonymousUrl(applicationContext); + urls = urls.stream().filter(url -> !url.equals("/")).collect(Collectors.toSet()); + String regExp = "^(?!" + apiPath + String.join("|" + apiPath, urls) + ").*$"; return SecurityContext.builder() .securityReferences(defaultAuth()) - // 表示 /auth/code、/auth/login 接口不需要使用securitySchemes即不需要带token - .operationSelector(o->o.requestMappingPattern().matches("^(?!/auth/code|/auth/login).*$")) + .operationSelector(o->o.requestMappingPattern() + // 排除不需要认证的接口 + .matches(regExp)) .build(); } diff --git a/eladmin/eladmin-common/src/main/java/me/zhengjie/utils/AnonTagUtils.java b/eladmin/eladmin-common/src/main/java/me/zhengjie/utils/AnonTagUtils.java new file mode 100644 index 0000000..8672a22 --- /dev/null +++ b/eladmin/eladmin-common/src/main/java/me/zhengjie/utils/AnonTagUtils.java @@ -0,0 +1,102 @@ +/* + * Copyright 2019-2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package me.zhengjie.utils; + +import me.zhengjie.annotation.AnonymousAccess; +import me.zhengjie.utils.enums.RequestMethodEnum; +import org.springframework.context.ApplicationContext; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.mvc.method.RequestMappingInfo; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; +import java.util.*; + +/** + * @author Zheng Jie + * @description 匿名标记工具 + * @date 2025-01-13 + **/ +public class AnonTagUtils { + + /** + * 获取匿名标记的URL + * @param applicationContext / + * @return / + */ + public static Map> getAnonymousUrl(ApplicationContext applicationContext){ + RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping) applicationContext.getBean("requestMappingHandlerMapping"); + Map handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods(); + Map> anonymousUrls = new HashMap<>(8); + // 获取匿名标记 + Set get = new HashSet<>(); + Set post = new HashSet<>(); + Set put = new HashSet<>(); + Set patch = new HashSet<>(); + Set delete = new HashSet<>(); + Set all = new HashSet<>(); + for (Map.Entry infoEntry : handlerMethodMap.entrySet()) { + HandlerMethod handlerMethod = infoEntry.getValue(); + AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class); + if (null != anonymousAccess) { + List requestMethods = new ArrayList<>(infoEntry.getKey().getMethodsCondition().getMethods()); + RequestMethodEnum request = RequestMethodEnum.find(requestMethods.isEmpty() ? RequestMethodEnum.ALL.getType() : requestMethods.get(0).name()); + if (infoEntry.getKey().getPatternsCondition()!=null) { + switch (Objects.requireNonNull(request)) { + case GET: + get.addAll(infoEntry.getKey().getPatternsCondition().getPatterns()); + break; + case POST: + post.addAll(infoEntry.getKey().getPatternsCondition().getPatterns()); + break; + case PUT: + put.addAll(infoEntry.getKey().getPatternsCondition().getPatterns()); + break; + case PATCH: + patch.addAll(infoEntry.getKey().getPatternsCondition().getPatterns()); + break; + case DELETE: + delete.addAll(infoEntry.getKey().getPatternsCondition().getPatterns()); + break; + default: + all.addAll(infoEntry.getKey().getPatternsCondition().getPatterns()); + break; + } + } + } + } + anonymousUrls.put(RequestMethodEnum.GET.getType(), get); + anonymousUrls.put(RequestMethodEnum.POST.getType(), post); + anonymousUrls.put(RequestMethodEnum.PUT.getType(), put); + anonymousUrls.put(RequestMethodEnum.PATCH.getType(), patch); + anonymousUrls.put(RequestMethodEnum.DELETE.getType(), delete); + anonymousUrls.put(RequestMethodEnum.ALL.getType(), all); + return anonymousUrls; + } + + /** + * 获取所有匿名标记的URL + * @param applicationContext / + * @return / + */ + public static Set getAllAnonymousUrl(ApplicationContext applicationContext){ + Set allUrl = new HashSet<>(); + Map> anonymousUrls = getAnonymousUrl(applicationContext); + for (String key : anonymousUrls.keySet()) { + allUrl.addAll(anonymousUrls.get(key)); + } + return allUrl; + } +} diff --git a/eladmin/eladmin-system/src/main/java/me/zhengjie/AppRun.java b/eladmin/eladmin-system/src/main/java/me/zhengjie/AppRun.java index 77bf42d..83eb72a 100644 --- a/eladmin/eladmin-system/src/main/java/me/zhengjie/AppRun.java +++ b/eladmin/eladmin-system/src/main/java/me/zhengjie/AppRun.java @@ -46,7 +46,6 @@ public class AppRun { springApplication.addListeners(new ApplicationPidFileWriter()); springApplication.run(args); log.info("---------------------------------------------"); - log.info("Backend service started successfully"); log.info("Local: {}", "http://localhost:8000"); log.info("Swagger: {}", "http://localhost:8000/doc.html"); log.info("---------------------------------------------"); @@ -59,7 +58,6 @@ public class AppRun { /** * 访问首页提示 - * * @return / */ @AnonymousGetMapping("/") diff --git a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/security/config/SpringSecurityConfig.java b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/security/config/SpringSecurityConfig.java index ad886f3..0a77629 100644 --- a/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/security/config/SpringSecurityConfig.java +++ b/eladmin/eladmin-system/src/main/java/me/zhengjie/modules/security/config/SpringSecurityConfig.java @@ -16,11 +16,11 @@ package me.zhengjie.modules.security.config; import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.AnonymousAccess; import me.zhengjie.modules.security.config.bean.SecurityProperties; import me.zhengjie.modules.security.security.*; import me.zhengjie.modules.security.service.OnlineUserService; import me.zhengjie.modules.security.service.UserCacheManager; +import me.zhengjie.utils.AnonTagUtils; import me.zhengjie.utils.enums.RequestMethodEnum; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; @@ -35,11 +35,7 @@ import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.filter.CorsFilter; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.servlet.mvc.method.RequestMappingInfo; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import java.util.*; /** @@ -74,11 +70,8 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity httpSecurity) throws Exception { - // 搜寻匿名标记 url: @AnonymousAccess - RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping) applicationContext.getBean("requestMappingHandlerMapping"); - Map handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods(); // 获取匿名标记 - Map> anonymousUrls = getAnonymousUrl(handlerMethodMap); + Map> anonymousUrls = AnonTagUtils.getAnonymousUrl(applicationContext); httpSecurity // 禁用 CSRF .csrf().disable() @@ -140,49 +133,4 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { private TokenConfigurer securityConfigurerAdapter() { return new TokenConfigurer(tokenProvider, properties, onlineUserService, userCacheManager); } - - private Map> getAnonymousUrl(Map handlerMethodMap) { - Map> anonymousUrls = new HashMap<>(8); - Set get = new HashSet<>(); - Set post = new HashSet<>(); - Set put = new HashSet<>(); - Set patch = new HashSet<>(); - Set delete = new HashSet<>(); - Set all = new HashSet<>(); - for (Map.Entry infoEntry : handlerMethodMap.entrySet()) { - HandlerMethod handlerMethod = infoEntry.getValue(); - AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class); - if (null != anonymousAccess) { - List requestMethods = new ArrayList<>(infoEntry.getKey().getMethodsCondition().getMethods()); - RequestMethodEnum request = RequestMethodEnum.find(requestMethods.size() == 0 ? RequestMethodEnum.ALL.getType() : requestMethods.get(0).name()); - switch (Objects.requireNonNull(request)) { - case GET: - get.addAll(infoEntry.getKey().getPatternsCondition().getPatterns()); - break; - case POST: - post.addAll(infoEntry.getKey().getPatternsCondition().getPatterns()); - break; - case PUT: - put.addAll(infoEntry.getKey().getPatternsCondition().getPatterns()); - break; - case PATCH: - patch.addAll(infoEntry.getKey().getPatternsCondition().getPatterns()); - break; - case DELETE: - delete.addAll(infoEntry.getKey().getPatternsCondition().getPatterns()); - break; - default: - all.addAll(infoEntry.getKey().getPatternsCondition().getPatterns()); - break; - } - } - } - anonymousUrls.put(RequestMethodEnum.GET.getType(), get); - anonymousUrls.put(RequestMethodEnum.POST.getType(), post); - anonymousUrls.put(RequestMethodEnum.PUT.getType(), put); - anonymousUrls.put(RequestMethodEnum.PATCH.getType(), patch); - anonymousUrls.put(RequestMethodEnum.DELETE.getType(), delete); - anonymousUrls.put(RequestMethodEnum.ALL.getType(), all); - return anonymousUrls; - } }