Commit c2ccfa3bd6c7acb8096c2e7dbdc0a08289804b71
1 parent
4890cf05
多模块重构 12:【新增】Spring Security 新增 AuthorizeRequestsCustomizer 抽象类, 自定义每个 Maven Module 的 URL 的安全配置
Showing
33 changed files
with
212 additions
and
137 deletions
http-client.env.json
| @@ -4,7 +4,7 @@ | @@ -4,7 +4,7 @@ | ||
| 4 | "token": "test1", | 4 | "token": "test1", |
| 5 | "adminTenentId": "1", | 5 | "adminTenentId": "1", |
| 6 | 6 | ||
| 7 | - "userApi": "http://127.0.0.1:48080/app-api", | 7 | + "appApi": "http://127.0.0.1:48080/app-api", |
| 8 | "appToken": "test1", | 8 | "appToken": "test1", |
| 9 | "appTenentId": "1" | 9 | "appTenentId": "1" |
| 10 | } | 10 | } |
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/AuthorizeRequestsCustomizer.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.security.config; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.web.config.WebProperties; | ||
| 4 | +import org.springframework.core.Ordered; | ||
| 5 | +import org.springframework.security.config.Customizer; | ||
| 6 | +import org.springframework.security.config.annotation.web.builders.HttpSecurity; | ||
| 7 | +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; | ||
| 8 | + | ||
| 9 | +import javax.annotation.Resource; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * 自定义的 URL 的安全配置 | ||
| 13 | + * 目的:每个 Maven Module 可以自定义规则! | ||
| 14 | + * | ||
| 15 | + * @author 芋道源码 | ||
| 16 | + */ | ||
| 17 | +public abstract class AuthorizeRequestsCustomizer | ||
| 18 | + implements Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry>, Ordered { | ||
| 19 | + | ||
| 20 | + @Resource | ||
| 21 | + private WebProperties webProperties; | ||
| 22 | + | ||
| 23 | + protected String buildAdminApi(String url) { | ||
| 24 | + return webProperties.getAdminApi().getPrefix() + url; | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + protected String buildAppApi(String url) { | ||
| 28 | + return webProperties.getAppApi().getPrefix() + url; | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + @Override | ||
| 32 | + public int getOrder() { | ||
| 33 | + return 0; | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | +} |
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java
| @@ -26,6 +26,8 @@ import org.springframework.security.web.util.matcher.RequestMatcher; | @@ -26,6 +26,8 @@ import org.springframework.security.web.util.matcher.RequestMatcher; | ||
| 26 | 26 | ||
| 27 | import javax.annotation.Resource; | 27 | import javax.annotation.Resource; |
| 28 | import javax.servlet.http.HttpServletRequest; | 28 | import javax.servlet.http.HttpServletRequest; |
| 29 | +import java.util.List; | ||
| 30 | +import java.util.function.Consumer; | ||
| 29 | 31 | ||
| 30 | /** | 32 | /** |
| 31 | * 自定义的 Spring Security 配置适配器实现 | 33 | * 自定义的 Spring Security 配置适配器实现 |
| @@ -62,14 +64,22 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap | @@ -62,14 +64,22 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap | ||
| 62 | @Resource | 64 | @Resource |
| 63 | private JWTAuthenticationTokenFilter authenticationTokenFilter; | 65 | private JWTAuthenticationTokenFilter authenticationTokenFilter; |
| 64 | 66 | ||
| 67 | +// /** | ||
| 68 | +// * 自定义的权限映射 Bean | ||
| 69 | +// * | ||
| 70 | +// * @see #configure(HttpSecurity) | ||
| 71 | +// */ | ||
| 72 | +// @Resource | ||
| 73 | +// private Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> | ||
| 74 | +// authorizeRequestsCustomizer; | ||
| 75 | + | ||
| 65 | /** | 76 | /** |
| 66 | - * 自定义的权限映射 Bean | 77 | + * 自定义的权限映射 Bean 们 |
| 67 | * | 78 | * |
| 68 | * @see #configure(HttpSecurity) | 79 | * @see #configure(HttpSecurity) |
| 69 | */ | 80 | */ |
| 70 | @Resource | 81 | @Resource |
| 71 | - private Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> | ||
| 72 | - authorizeRequestsCustomizer; | 82 | + private List<AuthorizeRequestsCustomizer> authorizeRequestsCustomizers; |
| 73 | 83 | ||
| 74 | /** | 84 | /** |
| 75 | * 由于 Spring Security 创建 AuthenticationManager 对象时,没声明 @Bean 注解,导致无法被注入 | 85 | * 由于 Spring Security 创建 AuthenticationManager 对象时,没声明 @Bean 注解,导致无法被注入 |
| @@ -126,44 +136,31 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap | @@ -126,44 +136,31 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap | ||
| 126 | StrUtil.equalsAny(request.getRequestURI(), buildAdminApi("/system/logout"), | 136 | StrUtil.equalsAny(request.getRequestURI(), buildAdminApi("/system/logout"), |
| 127 | buildAppApi("/member/logout"))); | 137 | buildAppApi("/member/logout"))); |
| 128 | 138 | ||
| 129 | - // 设置每个请求的权限 ①:全局共享规则 | ||
| 130 | - httpSecurity.authorizeRequests() | ||
| 131 | - // 登录的接口,可匿名访问 | ||
| 132 | - .antMatchers(buildAdminApi("/system/login"), buildAdminApi("/member/login")).anonymous() | 139 | + // 设置每个请求的权限 |
| 140 | + httpSecurity | ||
| 141 | + // ①:全局共享规则 | ||
| 142 | + .authorizeRequests() | ||
| 133 | // 静态资源,可匿名访问 | 143 | // 静态资源,可匿名访问 |
| 134 | .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll() | 144 | .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll() |
| 135 | - // 文件的获取接口,可匿名访问 | ||
| 136 | - .antMatchers(buildAdminApi("/infra/file/get/**")).anonymous() | ||
| 137 | - // Swagger 接口文档 | ||
| 138 | - .antMatchers("/swagger-ui.html").anonymous() | ||
| 139 | - .antMatchers("/swagger-resources/**").anonymous() | ||
| 140 | - .antMatchers("/webjars/**").anonymous() | ||
| 141 | - .antMatchers("/*/api-docs").anonymous() | ||
| 142 | - // Spring Boot Actuator 的安全配置 | ||
| 143 | - .antMatchers("/actuator").anonymous() | ||
| 144 | - .antMatchers("/actuator/**").anonymous() | ||
| 145 | - // Druid 监控 TODO 芋艿:等对接了 druid admin 后,在调整下。 | ||
| 146 | - .antMatchers("/druid/**").anonymous() | ||
| 147 | - // oAuth2 auth2/login/gitee TODO 芋艿:貌似可以删除 | ||
| 148 | - .antMatchers(buildAdminApi("/auth2/login/**")).anonymous() | ||
| 149 | - .antMatchers(buildAdminApi("/auth2/authorization/**")).anonymous() | ||
| 150 | - .antMatchers("/api/callback/**").anonymous() | ||
| 151 | - // 设置每个请求的权限 ②:每个项目的自定义规则 TODO 芋艿:改造成多个,方便每个模块自定义规则 | ||
| 152 | - .and().authorizeRequests(authorizeRequestsCustomizer) | ||
| 153 | - // 设置每个请求的权限 ③:兜底规则,必须认证 | ||
| 154 | - .authorizeRequests().anyRequest().authenticated() | 145 | + // 设置 App API 无需认证 |
| 146 | + .antMatchers(buildAppApi("/**")).permitAll() | ||
| 147 | + // ②:每个项目的自定义规则 | ||
| 148 | + .and().authorizeRequests(registry -> // 下面,循环设置自定义规则 | ||
| 149 | + authorizeRequestsCustomizers.forEach(customizer -> customizer.customize(registry))) | ||
| 150 | + // ③:兜底规则,必须认证 | ||
| 151 | + .authorizeRequests() | ||
| 152 | + .anyRequest().authenticated() | ||
| 155 | ; | 153 | ; |
| 154 | + | ||
| 156 | // 添加 JWT Filter | 155 | // 添加 JWT Filter |
| 157 | httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); | 156 | httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); |
| 158 | } | 157 | } |
| 159 | 158 | ||
| 160 | private String buildAdminApi(String url) { | 159 | private String buildAdminApi(String url) { |
| 161 | - // TODO 芋艿:多模块 | ||
| 162 | return webProperties.getAdminApi().getPrefix() + url; | 160 | return webProperties.getAdminApi().getPrefix() + url; |
| 163 | } | 161 | } |
| 164 | 162 | ||
| 165 | private String buildAppApi(String url) { | 163 | private String buildAppApi(String url) { |
| 166 | - // TODO 芋艿:多模块 | ||
| 167 | return webProperties.getAppApi().getPrefix() + url; | 164 | return webProperties.getAppApi().getPrefix() + url; |
| 168 | } | 165 | } |
| 169 | 166 |
yudao-module-infra/yudao-module-infra-impl/pom.xml
| @@ -90,6 +90,17 @@ | @@ -90,6 +90,17 @@ | ||
| 90 | <groupId>cn.smallbun.screw</groupId> | 90 | <groupId>cn.smallbun.screw</groupId> |
| 91 | <artifactId>screw-core</artifactId> <!-- 实现数据库文档 --> | 91 | <artifactId>screw-core</artifactId> <!-- 实现数据库文档 --> |
| 92 | </dependency> | 92 | </dependency> |
| 93 | + | ||
| 94 | + <!-- 监控相关 --> | ||
| 95 | + <dependency> | ||
| 96 | + <groupId>cn.iocoder.boot</groupId> | ||
| 97 | + <artifactId>yudao-spring-boot-starter-monitor</artifactId> | ||
| 98 | + </dependency> | ||
| 99 | + | ||
| 100 | + <dependency> | ||
| 101 | + <groupId>de.codecentric</groupId> | ||
| 102 | + <artifactId>spring-boot-admin-starter-server</artifactId> <!-- 实现 Spring Boot Admin Server 服务端 --> | ||
| 103 | + </dependency> | ||
| 93 | </dependencies> | 104 | </dependencies> |
| 94 | 105 | ||
| 95 | <build> | 106 | <build> |
yudao-server/src/main/java/cn/iocoder/yudao/server/framework/monitor/config/AdminServerConfiguration.java renamed to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/monitor/config/AdminServerConfiguration.java
| 1 | -package cn.iocoder.yudao.server.framework.monitor.config; | 1 | +package cn.iocoder.yudao.module.infra.framework.monitor.config; |
| 2 | 2 | ||
| 3 | import de.codecentric.boot.admin.server.config.EnableAdminServer; | 3 | import de.codecentric.boot.admin.server.config.EnableAdminServer; |
| 4 | import org.springframework.context.annotation.Configuration; | 4 | import org.springframework.context.annotation.Configuration; |
yudao-server/src/main/java/cn/iocoder/yudao/server/framework/monitor/package-info.java renamed to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/monitor/package-info.java
yudao-server/src/main/java/cn/iocoder/yudao/server/framework/monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md renamed to yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/monitor/《芋道 Spring Boot 监控工具 Admin 入门》.md
yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/security/config/InfraSecurityConfiguration.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.infra.framework.security.config; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer; | ||
| 4 | +import org.springframework.beans.factory.annotation.Value; | ||
| 5 | +import org.springframework.context.annotation.Bean; | ||
| 6 | +import org.springframework.context.annotation.Configuration; | ||
| 7 | +import org.springframework.security.config.annotation.web.builders.HttpSecurity; | ||
| 8 | +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * Infra 模块的 Security 配置 | ||
| 12 | + */ | ||
| 13 | +@Configuration | ||
| 14 | +public class InfraSecurityConfiguration { | ||
| 15 | + | ||
| 16 | + @Value("${spring.boot.admin.context-path:''}") | ||
| 17 | + private String adminSeverContextPath; | ||
| 18 | + | ||
| 19 | + @Bean("infraAuthorizeRequestsCustomizer") | ||
| 20 | + public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() { | ||
| 21 | + return new AuthorizeRequestsCustomizer() { | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) { | ||
| 25 | + // Swagger 接口文档 | ||
| 26 | + registry.antMatchers("/swagger-ui.html").anonymous() | ||
| 27 | + .antMatchers("/swagger-resources/**").anonymous() | ||
| 28 | + .antMatchers("/webjars/**").anonymous() | ||
| 29 | + .antMatchers("/*/api-docs").anonymous(); | ||
| 30 | + // Spring Boot Actuator 的安全配置 | ||
| 31 | + registry.antMatchers("/actuator").anonymous() | ||
| 32 | + .antMatchers("/actuator/**").anonymous(); | ||
| 33 | + // Druid 监控 | ||
| 34 | + registry.antMatchers("/druid/**").anonymous(); | ||
| 35 | + // Spring Boot Admin Server 的安全配置 | ||
| 36 | + registry.antMatchers(adminSeverContextPath).anonymous() | ||
| 37 | + .antMatchers(adminSeverContextPath + "/**").anonymous(); | ||
| 38 | + // 文件的获取接口,可匿名访问 | ||
| 39 | + registry.antMatchers(buildAdminApi("/infra/file/get/**"), buildAppApi("/infra/file/get/**")).anonymous(); | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + }; | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | +} |
yudao-module-infra/yudao-module-infra-impl/src/main/java/cn/iocoder/yudao/module/infra/framework/security/core/package-info.java
0 → 100644
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/framework/package-info.java deleted
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java
| @@ -202,6 +202,7 @@ public class MemberAuthServiceImpl implements MemberAuthService { | @@ -202,6 +202,7 @@ public class MemberAuthServiceImpl implements MemberAuthService { | ||
| 202 | if (user != null) { | 202 | if (user != null) { |
| 203 | reqDTO.setUserId(user.getId()); | 203 | reqDTO.setUserId(user.getId()); |
| 204 | } | 204 | } |
| 205 | + reqDTO.setUserType(getUserType().getValue()); | ||
| 205 | reqDTO.setUsername(mobile); | 206 | reqDTO.setUsername(mobile); |
| 206 | reqDTO.setUserAgent(ServletUtils.getUserAgent()); | 207 | reqDTO.setUserAgent(ServletUtils.getUserAgent()); |
| 207 | reqDTO.setUserIp(getClientIP()); | 208 | reqDTO.setUserIp(getClientIP()); |
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/LoginLogCreateReqDTO.java
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/security/config/SystemSecurityConfiguration.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.framework.security.config; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer; | ||
| 4 | +import org.springframework.context.annotation.Bean; | ||
| 5 | +import org.springframework.context.annotation.Configuration; | ||
| 6 | +import org.springframework.security.config.annotation.web.builders.HttpSecurity; | ||
| 7 | +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * System 模块的 Security 配置 | ||
| 11 | + */ | ||
| 12 | +@Configuration | ||
| 13 | +public class SystemSecurityConfiguration { | ||
| 14 | + | ||
| 15 | + @Bean("systemAuthorizeRequestsCustomizer") | ||
| 16 | + public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() { | ||
| 17 | + return new AuthorizeRequestsCustomizer() { | ||
| 18 | + | ||
| 19 | + @Override | ||
| 20 | + public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) { | ||
| 21 | + // 登录的接口,可匿名访问 | ||
| 22 | + registry.antMatchers(buildAdminApi("/system/login")).anonymous(); | ||
| 23 | + // 验证码的接口 | ||
| 24 | + registry.antMatchers(buildAdminApi("/system/captcha/**")).anonymous(); | ||
| 25 | + // 获得租户编号的接口 | ||
| 26 | + registry.antMatchers(buildAdminApi("/system/tenant/get-id-by-name")).anonymous(); | ||
| 27 | + // 短信回调 API | ||
| 28 | + registry.antMatchers(buildAdminApi("/system/sms/callback/**")).anonymous(); | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + }; | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | +} |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/framework/security/core/package-info.java
0 → 100644
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java
| @@ -164,7 +164,7 @@ public class AdminAuthServiceImpl implements AdminAuthService { | @@ -164,7 +164,7 @@ public class AdminAuthServiceImpl implements AdminAuthService { | ||
| 164 | if (user != null) { | 164 | if (user != null) { |
| 165 | reqDTO.setUserId(user.getId()); | 165 | reqDTO.setUserId(user.getId()); |
| 166 | } | 166 | } |
| 167 | - reqDTO.setUserType(UserTypeEnum.ADMIN.getValue()); | 167 | + reqDTO.setUserType(getUserType().getValue()); |
| 168 | reqDTO.setUsername(username); | 168 | reqDTO.setUsername(username); |
| 169 | reqDTO.setUserAgent(ServletUtils.getUserAgent()); | 169 | reqDTO.setUserAgent(ServletUtils.getUserAgent()); |
| 170 | reqDTO.setUserIp(ServletUtils.getClientIP()); | 170 | reqDTO.setUserIp(ServletUtils.getClientIP()); |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/logger/LoginLogServiceImpl.java
| @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.system.convert.logger.LoginLogConvert; | @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.system.convert.logger.LoginLogConvert; | ||
| 8 | import cn.iocoder.yudao.module.system.dal.dataobject.logger.LoginLogDO; | 8 | import cn.iocoder.yudao.module.system.dal.dataobject.logger.LoginLogDO; |
| 9 | import cn.iocoder.yudao.module.system.dal.mysql.logger.LoginLogMapper; | 9 | import cn.iocoder.yudao.module.system.dal.mysql.logger.LoginLogMapper; |
| 10 | import org.springframework.stereotype.Service; | 10 | import org.springframework.stereotype.Service; |
| 11 | +import org.springframework.validation.annotation.Validated; | ||
| 11 | 12 | ||
| 12 | import javax.annotation.Resource; | 13 | import javax.annotation.Resource; |
| 13 | import java.util.List; | 14 | import java.util.List; |
| @@ -16,6 +17,7 @@ import java.util.List; | @@ -16,6 +17,7 @@ import java.util.List; | ||
| 16 | * 登录日志 Service 实现 | 17 | * 登录日志 Service 实现 |
| 17 | */ | 18 | */ |
| 18 | @Service | 19 | @Service |
| 20 | +@Validated | ||
| 19 | public class LoginLogServiceImpl implements LoginLogService { | 21 | public class LoginLogServiceImpl implements LoginLogService { |
| 20 | 22 | ||
| 21 | @Resource | 23 | @Resource |
yudao-server/pom.xml
| @@ -67,17 +67,6 @@ | @@ -67,17 +67,6 @@ | ||
| 67 | <artifactId>yudao-spring-boot-starter-protection</artifactId> | 67 | <artifactId>yudao-spring-boot-starter-protection</artifactId> |
| 68 | </dependency> | 68 | </dependency> |
| 69 | 69 | ||
| 70 | - <!-- 监控相关 --> | ||
| 71 | - <dependency> | ||
| 72 | - <groupId>cn.iocoder.boot</groupId> | ||
| 73 | - <artifactId>yudao-spring-boot-starter-monitor</artifactId> | ||
| 74 | - </dependency> | ||
| 75 | - | ||
| 76 | - <dependency> | ||
| 77 | - <groupId>de.codecentric</groupId> | ||
| 78 | - <artifactId>spring-boot-admin-starter-server</artifactId> <!-- 实现 Spring Boot Admin Server 服务端 --> | ||
| 79 | - </dependency> | ||
| 80 | - | ||
| 81 | </dependencies> | 70 | </dependencies> |
| 82 | 71 | ||
| 83 | <build> | 72 | <build> |
yudao-server/src/main/java/cn/iocoder/yudao/module/shop/controller/admin/package-info.java
0 → 100644
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/shop/controller/ShopOrderController.java renamed to yudao-server/src/main/java/cn/iocoder/yudao/module/shop/controller/app/AppShopOrderController.java
| 1 | -package cn.iocoder.yudao.userserver.modules.shop.controller; | 1 | +package cn.iocoder.yudao.module.shop.controller.app; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.coreservice.modules.pay.service.notify.vo.PayNotifyOrderReqVO; | ||
| 4 | -import cn.iocoder.yudao.coreservice.modules.pay.service.notify.vo.PayRefundOrderReqVO; | ||
| 5 | -import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayOrderCoreService; | ||
| 6 | -import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderCreateReqDTO; | ||
| 7 | -import cn.iocoder.yudao.coreservice.modules.pay.util.PaySeqUtils; | ||
| 8 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 9 | import cn.iocoder.yudao.framework.common.util.date.DateUtils; | 4 | import cn.iocoder.yudao.framework.common.util.date.DateUtils; |
| 10 | -import cn.iocoder.yudao.userserver.modules.shop.controller.vo.ShopOrderCreateRespVO; | 5 | +import cn.iocoder.yudao.module.pay.service.notify.vo.PayNotifyOrderReqVO; |
| 6 | +import cn.iocoder.yudao.module.pay.service.notify.vo.PayRefundOrderReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.pay.service.order.PayOrderService; | ||
| 8 | +import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderCreateReqDTO; | ||
| 9 | +import cn.iocoder.yudao.module.pay.util.PaySeqUtils; | ||
| 10 | +import cn.iocoder.yudao.module.shop.controller.app.vo.AppShopOrderCreateRespVO; | ||
| 11 | import io.swagger.annotations.Api; | 11 | import io.swagger.annotations.Api; |
| 12 | import io.swagger.annotations.ApiOperation; | 12 | import io.swagger.annotations.ApiOperation; |
| 13 | import lombok.extern.slf4j.Slf4j; | 13 | import lombok.extern.slf4j.Slf4j; |
| @@ -24,20 +24,20 @@ import java.time.Duration; | @@ -24,20 +24,20 @@ import java.time.Duration; | ||
| 24 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 24 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 25 | import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; | 25 | import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; |
| 26 | 26 | ||
| 27 | -@Api(tags = "商城订单") | 27 | +@Api(tags = "用户 APP - 商城订单") |
| 28 | @RestController | 28 | @RestController |
| 29 | @RequestMapping("/shop/order") | 29 | @RequestMapping("/shop/order") |
| 30 | @Validated | 30 | @Validated |
| 31 | @Slf4j | 31 | @Slf4j |
| 32 | -public class ShopOrderController { | 32 | +public class AppShopOrderController { |
| 33 | 33 | ||
| 34 | @Resource | 34 | @Resource |
| 35 | - private PayOrderCoreService payOrderCoreService; | 35 | + private PayOrderService payOrderService; |
| 36 | 36 | ||
| 37 | @PostMapping("/create") | 37 | @PostMapping("/create") |
| 38 | @ApiOperation("创建商城订单") | 38 | @ApiOperation("创建商城订单") |
| 39 | // @PreAuthenticated // TODO 暂时不加登陆验证,前端暂时没做好 | 39 | // @PreAuthenticated // TODO 暂时不加登陆验证,前端暂时没做好 |
| 40 | - public CommonResult<ShopOrderCreateRespVO> create() { | 40 | + public CommonResult<AppShopOrderCreateRespVO> create() { |
| 41 | // 假装创建商城订单 | 41 | // 假装创建商城订单 |
| 42 | Long shopOrderId = System.currentTimeMillis(); | 42 | Long shopOrderId = System.currentTimeMillis(); |
| 43 | 43 | ||
| @@ -50,10 +50,10 @@ public class ShopOrderController { | @@ -50,10 +50,10 @@ public class ShopOrderController { | ||
| 50 | reqDTO.setBody("内容:" + shopOrderId); | 50 | reqDTO.setBody("内容:" + shopOrderId); |
| 51 | reqDTO.setAmount(200); // 单位:分 | 51 | reqDTO.setAmount(200); // 单位:分 |
| 52 | reqDTO.setExpireTime(DateUtils.addTime(Duration.ofDays(1))); | 52 | reqDTO.setExpireTime(DateUtils.addTime(Duration.ofDays(1))); |
| 53 | - Long payOrderId = payOrderCoreService.createPayOrder(reqDTO); | 53 | + Long payOrderId = payOrderService.createPayOrder(reqDTO); |
| 54 | 54 | ||
| 55 | // 拼接返回 | 55 | // 拼接返回 |
| 56 | - return success(ShopOrderCreateRespVO.builder().id(shopOrderId) | 56 | + return success(AppShopOrderCreateRespVO.builder().id(shopOrderId) |
| 57 | .payOrderId(payOrderId).build()); | 57 | .payOrderId(payOrderId).build()); |
| 58 | } | 58 | } |
| 59 | 59 |
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/shop/controller/vo/ShopOrderCreateRespVO.java renamed to yudao-server/src/main/java/cn/iocoder/yudao/module/shop/controller/app/vo/AppShopOrderCreateRespVO.java
| 1 | -package cn.iocoder.yudao.userserver.modules.shop.controller.vo; | 1 | +package cn.iocoder.yudao.module.shop.controller.app.vo; |
| 2 | 2 | ||
| 3 | import io.swagger.annotations.ApiModel; | 3 | import io.swagger.annotations.ApiModel; |
| 4 | import io.swagger.annotations.ApiModelProperty; | 4 | import io.swagger.annotations.ApiModelProperty; |
| @@ -6,11 +6,11 @@ import lombok.AllArgsConstructor; | @@ -6,11 +6,11 @@ import lombok.AllArgsConstructor; | ||
| 6 | import lombok.Builder; | 6 | import lombok.Builder; |
| 7 | import lombok.Data; | 7 | import lombok.Data; |
| 8 | 8 | ||
| 9 | -@ApiModel("商城订单创建 Response VO") | 9 | +@ApiModel("用户 APP - 商城订单创建 Response VO") |
| 10 | @Data | 10 | @Data |
| 11 | @Builder | 11 | @Builder |
| 12 | @AllArgsConstructor | 12 | @AllArgsConstructor |
| 13 | -public class ShopOrderCreateRespVO { | 13 | +public class AppShopOrderCreateRespVO { |
| 14 | 14 | ||
| 15 | @ApiModelProperty(value = "商城订单编号", required = true, example = "1024") | 15 | @ApiModelProperty(value = "商城订单编号", required = true, example = "1024") |
| 16 | private Long id; | 16 | private Long id; |
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/shop/package-info.java renamed to yudao-server/src/main/java/cn/iocoder/yudao/module/shop/package-info.java
yudao-server/src/main/java/cn/iocoder/yudao/server/framework/security/SecurityConfiguration.java deleted
| 1 | -package cn.iocoder.yudao.server.framework.security; | ||
| 2 | - | ||
| 3 | -import cn.iocoder.yudao.framework.web.config.WebProperties; | ||
| 4 | -import org.springframework.beans.factory.annotation.Value; | ||
| 5 | -import org.springframework.context.annotation.Bean; | ||
| 6 | -import org.springframework.context.annotation.Configuration; | ||
| 7 | -import org.springframework.security.config.Customizer; | ||
| 8 | -import org.springframework.security.config.annotation.web.builders.HttpSecurity; | ||
| 9 | -import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; | ||
| 10 | - | ||
| 11 | -import javax.annotation.Resource; | ||
| 12 | - | ||
| 13 | -@Configuration | ||
| 14 | -public class SecurityConfiguration { | ||
| 15 | - | ||
| 16 | - @Resource | ||
| 17 | - private WebProperties webProperties; | ||
| 18 | - | ||
| 19 | - @Value("${spring.boot.admin.context-path:''}") | ||
| 20 | - private String adminSeverContextPath; | ||
| 21 | - | ||
| 22 | - @Bean | ||
| 23 | - public Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer() { | ||
| 24 | - return registry -> { | ||
| 25 | - // 验证码的接口 | ||
| 26 | - registry.antMatchers(buildAdminApi("/system/captcha/**")).anonymous(); | ||
| 27 | - // 获得租户编号的接口 | ||
| 28 | - registry.antMatchers(buildAdminApi("/system/tenant/get-id-by-name")).anonymous(); | ||
| 29 | - // Spring Boot Admin Server 的安全配置 | ||
| 30 | - registry.antMatchers(adminSeverContextPath).anonymous() | ||
| 31 | - .antMatchers(adminSeverContextPath + "/**").anonymous(); | ||
| 32 | - // 短信回调 API | ||
| 33 | - registry.antMatchers(buildAdminApi("/system/sms/callback/**")).anonymous(); | ||
| 34 | - | ||
| 35 | - // 设置 App API 无需认证 | ||
| 36 | - registry.antMatchers(buildAppApi("/**")).permitAll(); | ||
| 37 | - }; | ||
| 38 | - } | ||
| 39 | - | ||
| 40 | - private String buildAdminApi(String url) { | ||
| 41 | - // TODO 芋艿:多模块 | ||
| 42 | - return webProperties.getAdminApi().getPrefix() + url; | ||
| 43 | - } | ||
| 44 | - | ||
| 45 | - private String buildAppApi(String url) { | ||
| 46 | - // TODO 芋艿:多模块 | ||
| 47 | - return webProperties.getAppApi().getPrefix() + url; | ||
| 48 | - } | ||
| 49 | - | ||
| 50 | -} |
yudao-server/src/main/resources/application.yaml
| @@ -20,6 +20,10 @@ spring: | @@ -20,6 +20,10 @@ spring: | ||
| 20 | write-durations-as-timestamps: true # 设置 Duration 的格式,使用时间戳 | 20 | write-durations-as-timestamps: true # 设置 Duration 的格式,使用时间戳 |
| 21 | fail-on-empty-beans: false # 允许序列化无属性的 Bean | 21 | fail-on-empty-beans: false # 允许序列化无属性的 Bean |
| 22 | 22 | ||
| 23 | + # 静态资源 | ||
| 24 | + mvc: | ||
| 25 | + static-path-pattern: /static/** | ||
| 26 | + | ||
| 23 | # 工作流 Activiti 配置 | 27 | # 工作流 Activiti 配置 |
| 24 | activiti: | 28 | activiti: |
| 25 | # 1. false: 默认值,activiti启动时,对比数据库表中保存的版本,如果不匹配。将抛出异常 | 29 | # 1. false: 默认值,activiti启动时,对比数据库表中保存的版本,如果不匹配。将抛出异常 |
yudao-user-server/src/main/resources/static/MP_verify_DKOvVzFP7vPwwHx2.txt renamed to yudao-server/src/main/resources/static/MP_verify_DKOvVzFP7vPwwHx2.txt
yudao-user-server/src/main/resources/static/READMD.md renamed to yudao-server/src/main/resources/static/READMD.md
yudao-user-server/src/main/resources/static/pay_alipay_qr.html renamed to yudao-server/src/main/resources/static/pay_alipay_qr.html
| @@ -24,11 +24,11 @@ | @@ -24,11 +24,11 @@ | ||
| 24 | <script> | 24 | <script> |
| 25 | let shopOrderId = undefined; | 25 | let shopOrderId = undefined; |
| 26 | let payOrderId = undefined; | 26 | let payOrderId = undefined; |
| 27 | - let server = 'http://127.0.0.1:28080'; | 27 | + let server = 'http://127.0.0.1:48080'; |
| 28 | $(function() { | 28 | $(function() { |
| 29 | // 自动发起商城订单编号 | 29 | // 自动发起商城订单编号 |
| 30 | $.ajax({ | 30 | $.ajax({ |
| 31 | - url: server + "/api/shop/order/create", | 31 | + url: server + "/app-api/shop/order/create", |
| 32 | method: 'POST', | 32 | method: 'POST', |
| 33 | success: function( result ) { | 33 | success: function( result ) { |
| 34 | if (result.code !== 0) { | 34 | if (result.code !== 0) { |
| @@ -46,7 +46,7 @@ | @@ -46,7 +46,7 @@ | ||
| 46 | $( "#alipay_wap").on( "click", function() { | 46 | $( "#alipay_wap").on( "click", function() { |
| 47 | // 提交支付 | 47 | // 提交支付 |
| 48 | $.ajax({ | 48 | $.ajax({ |
| 49 | - url: server + "/api/pay/order/submit", | 49 | + url: server + "/app-api/pay/order/submit", |
| 50 | method: 'POST', | 50 | method: 'POST', |
| 51 | dataType: "json", | 51 | dataType: "json", |
| 52 | contentType: "application/json", | 52 | contentType: "application/json", |
yudao-user-server/src/main/resources/static/pay_alipay_wap.html renamed to yudao-server/src/main/resources/static/pay_alipay_wap.html
| @@ -17,13 +17,13 @@ | @@ -17,13 +17,13 @@ | ||
| 17 | 17 | ||
| 18 | let shopOrderId = undefined; | 18 | let shopOrderId = undefined; |
| 19 | let payOrderId = undefined; | 19 | let payOrderId = undefined; |
| 20 | - let server = 'http://127.0.0.1:28080'; | 20 | + let server = 'http://127.0.0.1:48080'; |
| 21 | //let server = 'http://niubi.natapp1.cc'; | 21 | //let server = 'http://niubi.natapp1.cc'; |
| 22 | 22 | ||
| 23 | $(function() { | 23 | $(function() { |
| 24 | // 自动发起商城订单编号 | 24 | // 自动发起商城订单编号 |
| 25 | $.ajax({ | 25 | $.ajax({ |
| 26 | - url: server + "/api/shop/order/create", | 26 | + url: server + "/app-api/shop/order/create", |
| 27 | method: 'POST', | 27 | method: 'POST', |
| 28 | success: function( result ) { | 28 | success: function( result ) { |
| 29 | if (result.code !== 0) { | 29 | if (result.code !== 0) { |
| @@ -41,7 +41,7 @@ | @@ -41,7 +41,7 @@ | ||
| 41 | $( "#alipay_wap").on( "click", function() { | 41 | $( "#alipay_wap").on( "click", function() { |
| 42 | // 提交支付 | 42 | // 提交支付 |
| 43 | $.ajax({ | 43 | $.ajax({ |
| 44 | - url: server + "/api/pay/order/submit", | 44 | + url: server + "/app-api/pay/order/submit", |
| 45 | method: 'POST', | 45 | method: 'POST', |
| 46 | dataType: "json", | 46 | dataType: "json", |
| 47 | contentType: "application/json", | 47 | contentType: "application/json", |
yudao-user-server/src/main/resources/static/pay_wx_pub.html renamed to yudao-server/src/main/resources/static/pay_wx_pub.html
| @@ -16,7 +16,7 @@ | @@ -16,7 +16,7 @@ | ||
| 16 | <script> | 16 | <script> |
| 17 | let shopOrderId = undefined; | 17 | let shopOrderId = undefined; |
| 18 | let payOrderId = undefined; | 18 | let payOrderId = undefined; |
| 19 | - // let server = 'http://127.0.0.1:28080'; | 19 | + // let server = 'http://127.0.0.1:48080'; |
| 20 | let server = 'http://niubi.natapp1.cc'; | 20 | let server = 'http://niubi.natapp1.cc'; |
| 21 | // TODO openid | 21 | // TODO openid |
| 22 | let openid = "ockUAwIZ-0OeMZl9ogcZ4ILrGba0"; | 22 | let openid = "ockUAwIZ-0OeMZl9ogcZ4ILrGba0"; |
| @@ -24,7 +24,7 @@ | @@ -24,7 +24,7 @@ | ||
| 24 | // 获得 JsapiTicket | 24 | // 获得 JsapiTicket |
| 25 | // 参考 https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html 文档 | 25 | // 参考 https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html 文档 |
| 26 | $.ajax({ | 26 | $.ajax({ |
| 27 | - url: server + "/api/wx/mp/create-jsapi-signature?url=" + document.location.href, | 27 | + url: server + "/app-api/wx/mp/create-jsapi-signature?url=" + document.location.href, |
| 28 | method: 'POST', | 28 | method: 'POST', |
| 29 | success: function( result ) { | 29 | success: function( result ) { |
| 30 | if (result.code !== 0) { | 30 | if (result.code !== 0) { |
| @@ -42,7 +42,7 @@ | @@ -42,7 +42,7 @@ | ||
| 42 | 42 | ||
| 43 | // 自动发起商城订单编号 | 43 | // 自动发起商城订单编号 |
| 44 | $.ajax({ | 44 | $.ajax({ |
| 45 | - url: server + "/api/shop/order/create", | 45 | + url: server + "/app-api/shop/order/create", |
| 46 | method: 'POST', | 46 | method: 'POST', |
| 47 | success: function( result ) { | 47 | success: function( result ) { |
| 48 | if (result.code !== 0) { | 48 | if (result.code !== 0) { |
| @@ -78,7 +78,7 @@ | @@ -78,7 +78,7 @@ | ||
| 78 | // 参考 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6 文档 | 78 | // 参考 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6 文档 |
| 79 | // 参考 https://segmentfault.com/a/1190000020704650 文档 | 79 | // 参考 https://segmentfault.com/a/1190000020704650 文档 |
| 80 | $.ajax({ | 80 | $.ajax({ |
| 81 | - url: server + "/api/pay/order/submit", | 81 | + url: server + "/app-api/pay/order/submit", |
| 82 | method: 'POST', | 82 | method: 'POST', |
| 83 | dataType: "json", | 83 | dataType: "json", |
| 84 | contentType: "application/json", | 84 | contentType: "application/json", |
yudao-user-server/src/main/resources/static/qrcode.min.js renamed to yudao-server/src/main/resources/static/qrcode.min.js
yudao-user-server/src/main/resources/static/social-login.html renamed to yudao-server/src/main/resources/static/social-login.html
| @@ -14,14 +14,14 @@ | @@ -14,14 +14,14 @@ | ||
| 14 | </body> | 14 | </body> |
| 15 | <script> | 15 | <script> |
| 16 | // let server = 'http://127.0.0.1:28080'; | 16 | // let server = 'http://127.0.0.1:28080'; |
| 17 | - let server = 'http://192.168.1.2:28080'; | 17 | + let server = 'http://192.168.1.2:48080'; |
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | // 微信公众号 | 20 | // 微信公众号 |
| 21 | $( "#wx_pub").on( "click", function() { | 21 | $( "#wx_pub").on( "click", function() { |
| 22 | // 获得授权链接 | 22 | // 获得授权链接 |
| 23 | $.ajax({ | 23 | $.ajax({ |
| 24 | - url: server + "/api/social-auth-redirect?type=31&redirectUri=" + | 24 | + url: server + "/app-api/social-auth-redirect?type=31&redirectUri=" + |
| 25 | encodeURIComponent(server + '/static/social-login2.html'), //重定向地址 | 25 | encodeURIComponent(server + '/static/social-login2.html'), //重定向地址 |
| 26 | method: 'GET', | 26 | method: 'GET', |
| 27 | success: function( result ) { | 27 | success: function( result ) { |
yudao-user-server/src/main/resources/static/social-login2.html renamed to yudao-server/src/main/resources/static/social-login2.html
| @@ -17,8 +17,8 @@ | @@ -17,8 +17,8 @@ | ||
| 17 | </div> | 17 | </div> |
| 18 | </body> | 18 | </body> |
| 19 | <script> | 19 | <script> |
| 20 | - // let server = 'http://127.0.0.1:28080'; | ||
| 21 | - let server = 'http://192.168.1.2:28080'; | 20 | + // let server = 'http://127.0.0.1:48080'; |
| 21 | + let server = 'http://192.168.1.2:48080'; | ||
| 22 | 22 | ||
| 23 | let type = 31; //登录类型 微信公众号 | 23 | let type = 31; //登录类型 微信公众号 |
| 24 | 24 | ||
| @@ -38,7 +38,7 @@ | @@ -38,7 +38,7 @@ | ||
| 38 | 38 | ||
| 39 | // 调用授权登录接口 | 39 | // 调用授权登录接口 |
| 40 | $.ajax({ | 40 | $.ajax({ |
| 41 | - url: server + "/api/social-login2", | 41 | + url: server + "/app-api/social-login2", |
| 42 | method: 'POST', | 42 | method: 'POST', |
| 43 | data: JSON.stringify(data), | 43 | data: JSON.stringify(data), |
| 44 | contentType: "application/json;charset=utf-8", | 44 | contentType: "application/json;charset=utf-8", |
| @@ -60,7 +60,7 @@ | @@ -60,7 +60,7 @@ | ||
| 60 | 'scene': 1 // 手机号登陆 类型 | 60 | 'scene': 1 // 手机号登陆 类型 |
| 61 | } | 61 | } |
| 62 | $.ajax({ | 62 | $.ajax({ |
| 63 | - url: server + "/api/send-sms-code", | 63 | + url: server + "/app-api/send-sms-code", |
| 64 | method: 'POST', | 64 | method: 'POST', |
| 65 | data: JSON.stringify(data), | 65 | data: JSON.stringify(data), |
| 66 | contentType: "application/json;charset=utf-8", | 66 | contentType: "application/json;charset=utf-8", |
yudao-user-server/src/main/resources/application.yaml
| @@ -20,9 +20,7 @@ spring: | @@ -20,9 +20,7 @@ spring: | ||
| 20 | write-durations-as-timestamps: true # 设置 Duration 的格式,使用时间戳 | 20 | write-durations-as-timestamps: true # 设置 Duration 的格式,使用时间戳 |
| 21 | fail-on-empty-beans: false # 允许序列化无属性的 Bean | 21 | fail-on-empty-beans: false # 允许序列化无属性的 Bean |
| 22 | 22 | ||
| 23 | - # 静态资源 | ||
| 24 | - mvc: | ||
| 25 | - static-path-pattern: /static/** | 23 | + |
| 26 | 24 | ||
| 27 | # MyBatis Plus 的配置项 | 25 | # MyBatis Plus 的配置项 |
| 28 | mybatis-plus: | 26 | mybatis-plus: |
更新日志.md
| @@ -26,6 +26,7 @@ TODO 待统计 | @@ -26,6 +26,7 @@ TODO 待统计 | ||
| 26 | 26 | ||
| 27 | *【重构】大模块按照多 Maven Module 的方式拆分,提升可维护性,为后续重构 onemall 提供基础 | 27 | *【重构】大模块按照多 Maven Module 的方式拆分,提升可维护性,为后续重构 onemall 提供基础 |
| 28 | *【新增】Spring Security 支持读取多种用户类型,从不同的数据库表,从而实现单项目提供管理后台、用户 APP 的不同 RESTful API 接口 | 28 | *【新增】Spring Security 支持读取多种用户类型,从不同的数据库表,从而实现单项目提供管理后台、用户 APP 的不同 RESTful API 接口 |
| 29 | +*【新增】Spring Security 新增 AuthorizeRequestsCustomizer 抽象类, 自定义每个 Maven Module 的 URL 的安全配置 | ||
| 29 | *【新增】代码生成器支持多 Maven Module 的方式生成代码,支持管理后台、用户 APP 两种场景的 RESTful API 的生成,支持 H2 SQL 脚本的生成 | 30 | *【新增】代码生成器支持多 Maven Module 的方式生成代码,支持管理后台、用户 APP 两种场景的 RESTful API 的生成,支持 H2 SQL 脚本的生成 |
| 30 | *【重构】将数据库文档调整到 tool 模块,更加明确 | 31 | *【重构】将数据库文档调整到 tool 模块,更加明确 |
| 31 | *【优化】代码生成器的前端展示效果,例如说 Java 包路径合并 | 32 | *【优化】代码生成器的前端展示效果,例如说 Java 包路径合并 |
| @@ -73,6 +74,7 @@ TODO 待统计 | @@ -73,6 +74,7 @@ TODO 待统计 | ||
| 73 | 74 | ||
| 74 | * 【修复】biz-data-permission 组件的缓存机制,导致部分 SQL 未进行数据过滤 | 75 | * 【修复】biz-data-permission 组件的缓存机制,导致部分 SQL 未进行数据过滤 |
| 75 | * 【修复】codegen 生成代码时,delete 接口补充 dataTypeClass 属性,避免 Swagger 打印 WARN 日志 | 76 | * 【修复】codegen 生成代码时,delete 接口补充 dataTypeClass 属性,避免 Swagger 打印 WARN 日志 |
| 77 | +* 【修复】Swagger 文档由于写错 `@ApiImplicitParam` 注解的 name 和 dataTypeClass 属性,导致文档生成失败 | ||
| 76 | 78 | ||
| 77 | ### 🔨 Dependency Upgrades | 79 | ### 🔨 Dependency Upgrades |
| 78 | 80 |