reactor:@TenantIgnore 添加在 Controller 时,自动添加到 TenantProperties 中
This commit is contained in:
parent
5a87b33df2
commit
be86cdfd51
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.tenant.config;
|
|||
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
|
||||
import cn.iocoder.yudao.framework.redis.config.YudaoCacheProperties;
|
||||
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
|
||||
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnoreAspect;
|
||||
import cn.iocoder.yudao.framework.tenant.core.db.TenantDatabaseInterceptor;
|
||||
import cn.iocoder.yudao.framework.tenant.core.job.TenantJobAspect;
|
||||
|
@ -19,11 +20,13 @@ import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
|
|||
import cn.iocoder.yudao.module.system.api.tenant.TenantApi;
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.data.redis.cache.BatchStrategies;
|
||||
|
@ -32,14 +35,24 @@ import org.springframework.data.redis.cache.RedisCacheManager;
|
|||
import org.springframework.data.redis.cache.RedisCacheWriter;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
import org.springframework.web.util.pattern.PathPattern;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
|
||||
@AutoConfiguration
|
||||
@ConditionalOnProperty(prefix = "yudao.tenant", value = "enable", matchIfMissing = true) // 允许使用 yudao.tenant.enable=false 禁用多租户
|
||||
@EnableConfigurationProperties(TenantProperties.class)
|
||||
public class YudaoTenantAutoConfiguration {
|
||||
|
||||
@Resource
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Bean
|
||||
public TenantFrameworkService tenantFrameworkService(TenantApi tenantApi) {
|
||||
return new TenantFrameworkServiceImpl(tenantApi);
|
||||
|
@ -67,13 +80,41 @@ public class YudaoTenantAutoConfiguration {
|
|||
// ========== WEB ==========
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean<TenantContextWebFilter> tenantContextWebFilter() {
|
||||
public FilterRegistrationBean<TenantContextWebFilter> tenantContextWebFilter(TenantProperties tenantProperties) {
|
||||
FilterRegistrationBean<TenantContextWebFilter> registrationBean = new FilterRegistrationBean<>();
|
||||
registrationBean.setFilter(new TenantContextWebFilter());
|
||||
registrationBean.setOrder(WebFilterOrderEnum.TENANT_CONTEXT_FILTER);
|
||||
addIgnoreUrls(tenantProperties);
|
||||
return registrationBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果 Controller 接口上,有 {@link TenantIgnore} 注解,那么添加到忽略的 URL 中
|
||||
*
|
||||
* @param tenantProperties 租户配置
|
||||
*/
|
||||
private void addIgnoreUrls(TenantProperties tenantProperties) {
|
||||
// 获得接口对应的 HandlerMethod 集合
|
||||
RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping)
|
||||
applicationContext.getBean("requestMappingHandlerMapping");
|
||||
Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();
|
||||
// 获得有 @TenantIgnore 注解的接口
|
||||
for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethodMap.entrySet()) {
|
||||
HandlerMethod handlerMethod = entry.getValue();
|
||||
if (!handlerMethod.hasMethodAnnotation(TenantIgnore.class)) {
|
||||
continue;
|
||||
}
|
||||
// 添加到忽略的 URL 中
|
||||
if (entry.getKey().getPatternsCondition() != null) {
|
||||
tenantProperties.getIgnoreUrls().addAll(entry.getKey().getPatternsCondition().getPatterns());
|
||||
}
|
||||
if (entry.getKey().getPathPatternsCondition() != null) {
|
||||
tenantProperties.getIgnoreUrls().addAll(
|
||||
convertList(entry.getKey().getPathPatternsCondition().getPatterns(), PathPattern::getPatternString));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== Security ==========
|
||||
|
||||
@Bean
|
||||
|
|
|
@ -6,6 +6,7 @@ import cn.hutool.core.util.URLUtil;
|
|||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
|
||||
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.*;
|
||||
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
|
||||
import cn.iocoder.yudao.module.infra.service.file.FileService;
|
||||
|
@ -76,6 +77,7 @@ public class FileController {
|
|||
|
||||
@GetMapping("/{configId}/get/**")
|
||||
@PermitAll
|
||||
@TenantIgnore
|
||||
@Operation(summary = "下载文件")
|
||||
@Parameter(name = "configId", description = "配置编号", required = true)
|
||||
public void getFileContent(HttpServletRequest request,
|
||||
|
|
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.mp.controller.admin.open;
|
|||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
|
||||
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.open.vo.MpOpenCheckSignatureReqVO;
|
||||
import cn.iocoder.yudao.module.mp.controller.admin.open.vo.MpOpenHandleMessageReqVO;
|
||||
|
@ -35,26 +36,6 @@ public class MpOpenController {
|
|||
@Resource
|
||||
private MpAccountService mpAccountService;
|
||||
|
||||
/**
|
||||
* 接收微信公众号的校验签名
|
||||
*
|
||||
* 对应 <a href="https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html">文档</a>
|
||||
*/
|
||||
@Operation(summary = "校验签名") // 参见
|
||||
@GetMapping(value = "/{appId}", produces = "text/plain;charset=utf-8")
|
||||
public String checkSignature(@PathVariable("appId") String appId,
|
||||
MpOpenCheckSignatureReqVO reqVO) {
|
||||
log.info("[checkSignature][appId({}) 接收到来自微信服务器的认证消息({})]", appId, reqVO);
|
||||
// 校验请求签名
|
||||
WxMpService wxMpService = mpServiceFactory.getRequiredMpService(appId);
|
||||
// 校验通过
|
||||
if (wxMpService.checkSignature(reqVO.getTimestamp(), reqVO.getNonce(), reqVO.getSignature())) {
|
||||
return reqVO.getEchostr();
|
||||
}
|
||||
// 校验不通过
|
||||
return "非法请求";
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收微信公众号的消息推送
|
||||
*
|
||||
|
@ -62,6 +43,7 @@ public class MpOpenController {
|
|||
*/
|
||||
@Operation(summary = "处理消息")
|
||||
@PostMapping(value = "/{appId}", produces = "application/xml; charset=UTF-8")
|
||||
@TenantIgnore
|
||||
public String handleMessage(@PathVariable("appId") String appId,
|
||||
@RequestBody String content,
|
||||
MpOpenHandleMessageReqVO reqVO) {
|
||||
|
@ -79,6 +61,27 @@ public class MpOpenController {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收微信公众号的校验签名
|
||||
*
|
||||
* 对应 <a href="https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html">文档</a>
|
||||
*/
|
||||
@Operation(summary = "校验签名") // 参见
|
||||
@GetMapping(value = "/{appId}", produces = "text/plain;charset=utf-8")
|
||||
@TenantIgnore
|
||||
public String checkSignature(@PathVariable("appId") String appId,
|
||||
MpOpenCheckSignatureReqVO reqVO) {
|
||||
log.info("[checkSignature][appId({}) 接收到来自微信服务器的认证消息({})]", appId, reqVO);
|
||||
// 校验请求签名
|
||||
WxMpService wxMpService = mpServiceFactory.getRequiredMpService(appId);
|
||||
// 校验通过
|
||||
if (wxMpService.checkSignature(reqVO.getTimestamp(), reqVO.getNonce(), reqVO.getSignature())) {
|
||||
return reqVO.getEchostr();
|
||||
}
|
||||
// 校验不通过
|
||||
return "非法请求";
|
||||
}
|
||||
|
||||
private String handleMessage0(String appId, String content, MpOpenHandleMessageReqVO reqVO) {
|
||||
// 校验请求签名
|
||||
WxMpService mppService = mpServiceFactory.getRequiredMpService(appId);
|
||||
|
|
|
@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.pay.core.client.PayClient;
|
|||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.PayTransferRespDTO;
|
||||
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskDetailRespVO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO;
|
||||
import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskRespVO;
|
||||
|
@ -62,6 +63,7 @@ public class PayNotifyController {
|
|||
@PostMapping(value = "/order/{channelId}")
|
||||
@Operation(summary = "支付渠道的统一【支付】回调")
|
||||
@PermitAll
|
||||
@TenantIgnore
|
||||
public String notifyOrder(@PathVariable("channelId") Long channelId,
|
||||
@RequestParam(required = false) Map<String, String> params,
|
||||
@RequestBody(required = false) String body) {
|
||||
|
@ -82,6 +84,7 @@ public class PayNotifyController {
|
|||
@PostMapping(value = "/refund/{channelId}")
|
||||
@Operation(summary = "支付渠道的统一【退款】回调")
|
||||
@PermitAll
|
||||
@TenantIgnore
|
||||
public String notifyRefund(@PathVariable("channelId") Long channelId,
|
||||
@RequestParam(required = false) Map<String, String> params,
|
||||
@RequestBody(required = false) String body) {
|
||||
|
@ -102,6 +105,7 @@ public class PayNotifyController {
|
|||
@PostMapping(value = "/transfer/{channelId}")
|
||||
@Operation(summary = "支付渠道的统一【转账】回调")
|
||||
@PermitAll
|
||||
@TenantIgnore
|
||||
public String notifyTransfer(@PathVariable("channelId") Long channelId,
|
||||
@RequestParam(required = false) Map<String, String> params,
|
||||
@RequestBody(required = false) String body) {
|
||||
|
|
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.controller.admin.captcha;
|
|||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
|
||||
import com.anji.captcha.model.common.ResponseModel;
|
||||
import com.anji.captcha.model.vo.CaptchaVO;
|
||||
import com.anji.captcha.service.CaptchaService;
|
||||
|
@ -26,6 +27,7 @@ public class CaptchaController {
|
|||
@PostMapping({"/get"})
|
||||
@Operation(summary = "获得验证码")
|
||||
@PermitAll
|
||||
@TenantIgnore
|
||||
public ResponseModel get(@RequestBody CaptchaVO data, HttpServletRequest request) {
|
||||
assert request.getRemoteHost() != null;
|
||||
data.setBrowserInfo(getRemoteId(request));
|
||||
|
@ -35,6 +37,7 @@ public class CaptchaController {
|
|||
@PostMapping("/check")
|
||||
@Operation(summary = "校验验证码")
|
||||
@PermitAll
|
||||
@TenantIgnore
|
||||
public ResponseModel check(@RequestBody CaptchaVO data, HttpServletRequest request) {
|
||||
data.setBrowserInfo(getRemoteId(request));
|
||||
return captchaService.check(data);
|
||||
|
|
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.controller.admin.sms;
|
|||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
|
||||
import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsChannelEnum;
|
||||
import cn.iocoder.yudao.module.system.service.sms.SmsSendService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
|
@ -24,6 +25,7 @@ public class SmsCallbackController {
|
|||
|
||||
@PostMapping("/aliyun")
|
||||
@PermitAll
|
||||
@TenantIgnore
|
||||
@Operation(summary = "阿里云短信的回调", description = "参见 https://help.aliyun.com/document_detail/120998.html 文档")
|
||||
public CommonResult<Boolean> receiveAliyunSmsStatus(HttpServletRequest request) throws Throwable {
|
||||
String text = ServletUtils.getBody(request);
|
||||
|
@ -33,6 +35,7 @@ public class SmsCallbackController {
|
|||
|
||||
@PostMapping("/tencent")
|
||||
@PermitAll
|
||||
@TenantIgnore
|
||||
@Operation(summary = "腾讯云短信的回调", description = "参见 https://cloud.tencent.com/document/product/382/52077 文档")
|
||||
public CommonResult<Boolean> receiveTencentSmsStatus(HttpServletRequest request) throws Throwable {
|
||||
String text = ServletUtils.getBody(request);
|
||||
|
@ -43,6 +46,7 @@ public class SmsCallbackController {
|
|||
|
||||
@PostMapping("/huawei")
|
||||
@PermitAll
|
||||
@TenantIgnore
|
||||
@Operation(summary = "华为云短信的回调", description = "参见 https://support.huaweicloud.com/api-msgsms/sms_05_0003.html 文档")
|
||||
public CommonResult<Boolean> receiveHuaweiSmsStatus(@RequestBody String requestBody) throws Throwable {
|
||||
smsSendService.receiveSmsStatus(SmsChannelEnum.HUAWEI.getCode(), requestBody);
|
||||
|
@ -51,6 +55,7 @@ public class SmsCallbackController {
|
|||
|
||||
@PostMapping("/qiniu")
|
||||
@PermitAll
|
||||
@TenantIgnore
|
||||
@Operation(summary = "七牛云短信的回调", description = "参见 https://developer.qiniu.com/sms/5910/message-push 文档")
|
||||
public CommonResult<Boolean> receiveQiniuSmsStatus(@RequestBody String requestBody) throws Throwable {
|
||||
smsSendService.receiveSmsStatus(SmsChannelEnum.QINIU.getCode(), requestBody);
|
||||
|
|
|
@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
|||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantSaveReqVO;
|
||||
|
@ -39,6 +40,7 @@ public class TenantController {
|
|||
|
||||
@GetMapping("/get-id-by-name")
|
||||
@PermitAll
|
||||
@TenantIgnore
|
||||
@Operation(summary = "使用租户名,获得租户编号", description = "登录界面,根据用户的租户名,获得租户编号")
|
||||
@Parameter(name = "name", description = "租户名", required = true, example = "1024")
|
||||
public CommonResult<Long> getTenantIdByName(@RequestParam("name") String name) {
|
||||
|
@ -48,6 +50,7 @@ public class TenantController {
|
|||
|
||||
@GetMapping({ "simple-list" })
|
||||
@PermitAll
|
||||
@TenantIgnore
|
||||
@Operation(summary = "获取租户精简信息列表", description = "只包含被开启的租户,用于【首页】功能的选择租户选项")
|
||||
public CommonResult<List<TenantRespVO>> getTenantSimpleList() {
|
||||
List<TenantDO> list = tenantService.getTenantListByStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
|
@ -57,6 +60,7 @@ public class TenantController {
|
|||
|
||||
@GetMapping("/get-by-website")
|
||||
@PermitAll
|
||||
@TenantIgnore
|
||||
@Operation(summary = "使用域名,获得租户信息", description = "登录界面,根据用户的域名,获得租户信息")
|
||||
@Parameter(name = "website", description = "域名", required = true, example = "www.iocoder.cn")
|
||||
public CommonResult<TenantRespVO> getTenantByWebsite(@RequestParam("website") String website) {
|
||||
|
|
|
@ -273,16 +273,7 @@ yudao:
|
|||
tenant: # 多租户相关配置项
|
||||
enable: true
|
||||
ignore-urls:
|
||||
- /admin-api/system/tenant/get-id-by-name # 基于名字获取租户,不许带租户编号
|
||||
- /admin-api/system/tenant/get-by-website # 基于域名获取租户,不许带租户编号
|
||||
- /admin-api/system/tenant/simple-list # 获取租户列表,不许带租户编号
|
||||
- /admin-api/system/captcha/get # 获取图片验证码,和租户无关
|
||||
- /admin-api/system/captcha/check # 校验图片验证码,和租户无关
|
||||
- /admin-api/infra/file/*/get/** # 获取图片,和租户无关
|
||||
- /admin-api/system/sms/callback/* # 短信回调接口,无法带上租户编号
|
||||
- /admin-api/pay/notify/** # 支付回调通知,不携带租户编号
|
||||
- /jmreport/* # 积木报表,无法携带租户编号
|
||||
- /admin-api/mp/open/** # 微信公众号开放平台,微信回调接口,无法携带租户编号
|
||||
ignore-tables:
|
||||
- system_tenant
|
||||
- system_tenant_package
|
||||
|
|
Loading…
Reference in New Issue