后台服务修复

main
lj7788 2026-02-05 17:34:02 +08:00
parent 0e7ece7aca
commit 0143282340
5 changed files with 35 additions and 23 deletions

View File

@ -64,6 +64,18 @@ public class TenantSecurityWebFilter extends ApiRequestFilter {
@Override @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException { throws ServletException, IOException {
// 首先检查是否是忽略租户的 URL如果是则直接跳过所有租户相关检查
if (isIgnoreUrl(request)) {
Long tenantId = TenantContextHolder.getTenantId();
// 如果是允许忽略租户的 URL若未传递租户编号则默认忽略租户编号避免报错
if (tenantId == null) {
TenantContextHolder.setIgnore(true);
}
// 继续过滤
chain.doFilter(request, response);
return;
}
Long tenantId = TenantContextHolder.getTenantId(); Long tenantId = TenantContextHolder.getTenantId();
// 1. 登陆的用户,校验是否有权限访问该租户,避免越权问题。 // 1. 登陆的用户,校验是否有权限访问该租户,避免越权问题。
LoginUser user = SecurityFrameworkUtils.getLoginUser(); LoginUser user = SecurityFrameworkUtils.getLoginUser();
@ -83,27 +95,20 @@ public class TenantSecurityWebFilter extends ApiRequestFilter {
} }
} }
// 如果非允许忽略租户的 URL则校验租户是否合法 // 2. 如果请求未带租户的编号,不允许访问。
if (!isIgnoreUrl(request)) { if (tenantId == null) {
// 2. 如果请求未带租户的编号,不允许访问。 log.error("[doFilterInternal][URL({}/{}) 未传递租户编号]", request.getRequestURI(), request.getMethod());
if (tenantId == null) { ServletUtils.writeJSON(response, CommonResult.error(GlobalErrorCodeConstants.BAD_REQUEST.getCode(),
log.error("[doFilterInternal][URL({}/{}) 未传递租户编号]", request.getRequestURI(), request.getMethod()); "请求的租户标识未传递,请进行排查"));
ServletUtils.writeJSON(response, CommonResult.error(GlobalErrorCodeConstants.BAD_REQUEST.getCode(), return;
"请求的租户标识未传递,请进行排查")); }
return; // 3. 校验租户是合法,例如说被禁用、到期
} try {
// 3. 校验租户是合法,例如说被禁用、到期 tenantFrameworkService.validTenant(tenantId);
try { } catch (Throwable ex) {
tenantFrameworkService.validTenant(tenantId); CommonResult<?> result = globalExceptionHandler.allExceptionHandler(request, ex);
} catch (Throwable ex) { ServletUtils.writeJSON(response, result);
CommonResult<?> result = globalExceptionHandler.allExceptionHandler(request, ex); return;
ServletUtils.writeJSON(response, result);
return;
}
} else { // 如果是允许忽略租户的 URL若未传递租户编号则默认忽略租户编号避免报错
if (tenantId == null) {
TenantContextHolder.setIgnore(true);
}
} }
// 继续过滤 // 继续过滤

View File

@ -32,9 +32,14 @@ public interface OAuth2AccessTokenMapper extends BaseMapperX<OAuth2AccessTokenDO
.orderByDesc(OAuth2AccessTokenDO::getId)); .orderByDesc(OAuth2AccessTokenDO::getId));
} }
@TenantIgnore // 获取 token 的时候,需要忽略租户编号。原因是:一些场景下,可能不会传递 tenant-id 请求头,例如说文件上传、积木报表等等
default List<OAuth2AccessTokenDO> selectListByUserIdAndUserType(Long userId, Integer userType) { default List<OAuth2AccessTokenDO> selectListByUserIdAndUserType(Long userId, Integer userType) {
return selectList(OAuth2AccessTokenDO::getUserId, userId, return selectList(OAuth2AccessTokenDO::getUserId, userId,
OAuth2AccessTokenDO::getUserType, userType); OAuth2AccessTokenDO::getUserType, userType);
} }
@TenantIgnore // 删除 token 的时候,需要忽略租户编号。原因是:用户可能切换租户后登出,此时 token 的租户 ID 与当前租户不一致
default int deleteByIdIgnoreTenant(Long id) {
return delete(OAuth2AccessTokenDO::getId, id);
}
} }

View File

@ -147,7 +147,7 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
if (accessTokenDO == null) { if (accessTokenDO == null) {
return null; return null;
} }
oauth2AccessTokenMapper.deleteById(accessTokenDO.getId()); oauth2AccessTokenMapper.deleteByIdIgnoreTenant(accessTokenDO.getId());
oauth2AccessTokenRedisDAO.delete(accessToken); oauth2AccessTokenRedisDAO.delete(accessToken);
// 删除刷新令牌 // 删除刷新令牌
oauth2RefreshTokenMapper.deleteByRefreshToken(accessTokenDO.getRefreshToken()); oauth2RefreshTokenMapper.deleteByRefreshToken(accessTokenDO.getRefreshToken());
@ -162,7 +162,7 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
} }
accessTokens.forEach(accessToken -> { accessTokens.forEach(accessToken -> {
// 删除访问令牌 // 删除访问令牌
oauth2AccessTokenMapper.deleteById(accessToken.getId()); oauth2AccessTokenMapper.deleteByIdIgnoreTenant(accessToken.getId());
oauth2AccessTokenRedisDAO.delete(accessToken.getAccessToken()); oauth2AccessTokenRedisDAO.delete(accessToken.getAccessToken());
// 删除刷新令牌 // 删除刷新令牌
oauth2RefreshTokenMapper.deleteByRefreshToken(accessToken.getRefreshToken()); oauth2RefreshTokenMapper.deleteByRefreshToken(accessToken.getRefreshToken());

View File

@ -190,6 +190,7 @@ logging:
com.yanzhu.module.iot.dal.tdengine: DEBUG com.yanzhu.module.iot.dal.tdengine: DEBUG
com.yanzhu.module.iot.service.rule: debug com.yanzhu.module.iot.service.rule: debug
com.yanzhu.module.ai.dal.mysql: debug com.yanzhu.module.ai.dal.mysql: debug
com.yanzhu.module.product.dal.mysql: debug
org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿先禁用Spring Boot 3.X 存在部分错误的 WARN 提示 org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿先禁用Spring Boot 3.X 存在部分错误的 WARN 提示
# Flowable 工作流引擎配置 # Flowable 工作流引擎配置

View File

@ -67,6 +67,7 @@ flowable:
mybatis-plus: mybatis-plus:
configuration: configuration:
map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。 map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开启SQL语句打印到控制台
global-config: global-config:
db-config: db-config:
id-type: NONE # “智能”模式,基于 IdTypeEnvironmentPostProcessor + 数据源的类型,自动适配成 AUTO、INPUT 模式。 id-type: NONE # “智能”模式,基于 IdTypeEnvironmentPostProcessor + 数据源的类型,自动适配成 AUTO、INPUT 模式。