init
This commit is contained in:
@@ -10,6 +10,7 @@ import com.ruoyi.component.mybatis.config.MybatisPlusConfig;
|
||||
import com.ruoyi.component.redis.config.RedisConfig;
|
||||
import com.ruoyi.component.redis.properties.RedissonProperties;
|
||||
import com.ruoyi.component.tenant.core.TenantSaTokenDao;
|
||||
import com.ruoyi.component.tenant.filter.TenantFilter;
|
||||
import com.ruoyi.component.tenant.handle.PlusTenantLineHandler;
|
||||
import com.ruoyi.component.tenant.handle.TenantKeyPrefixHandler;
|
||||
import com.ruoyi.component.tenant.manager.TenantSpringCacheManager;
|
||||
@@ -20,6 +21,7 @@ import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
@@ -88,6 +90,17 @@ public class TenantConfig {
|
||||
return new TenantSpringCacheManager();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
@Bean
|
||||
public FilterRegistrationBean tenantFilter() {
|
||||
FilterRegistrationBean registration = new FilterRegistrationBean();
|
||||
registration.setFilter(new TenantFilter());
|
||||
registration.addUrlPatterns("/*");
|
||||
registration.setName("tenantFilter");
|
||||
registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
|
||||
return registration;
|
||||
}
|
||||
|
||||
/**
|
||||
* 多租户鉴权dao实现
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.ruoyi.component.tenant.filter;
|
||||
|
||||
|
||||
import cn.hutool.json.JSON;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.ruoyi.component.core.constant.TenantConstants;
|
||||
import com.ruoyi.component.core.domain.R;
|
||||
import com.ruoyi.component.core.util.ServletUtils;
|
||||
import com.ruoyi.component.core.util.StringUtils;
|
||||
import com.ruoyi.component.satoken.utils.LoginHelper;
|
||||
import com.ruoyi.component.tenant.helper.TenantHelper;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class TenantFilter implements Filter {
|
||||
public static final String TENANT_ID_HEADER = "Tenant-ID";
|
||||
|
||||
private static final Set<String> IGNORE_URL = new HashSet<>();
|
||||
static {
|
||||
IGNORE_URL.add("/login");
|
||||
IGNORE_URL.add("/captchaImage");
|
||||
}
|
||||
private static final AntPathMatcher ANT_PATH_MATCHER = new AntPathMatcher();
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
|
||||
if(!(servletRequest instanceof HttpServletRequest)){
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
return;
|
||||
}
|
||||
HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||
try {
|
||||
String requestURI = request.getRequestURI();
|
||||
for (String ignoreUrlMatch : IGNORE_URL) {
|
||||
boolean match = ANT_PATH_MATCHER.match(ignoreUrlMatch, requestURI);
|
||||
if(match){
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
return;
|
||||
}
|
||||
}
|
||||
String tenantHeader = request.getHeader(TENANT_ID_HEADER);
|
||||
boolean login = TenantHelper.isLogin();
|
||||
if(login){
|
||||
Long userId = LoginHelper.getUserId();
|
||||
if(TenantConstants.SUPER_ADMIN_ID.equals(userId)){
|
||||
TenantHelper.setTenantId(tenantHeader);
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(!StringUtils.isBlank(tenantHeader)){
|
||||
if(login){
|
||||
String tenantId = LoginHelper.getTenantId();
|
||||
if(tenantId == null || !tenantId.equals(tenantHeader)){
|
||||
ServletUtils.renderString(response, JSONUtil.toJsonStr(R.fail("平台错误")));
|
||||
return;
|
||||
}
|
||||
TenantHelper.setTenantId(tenantId);
|
||||
}else{
|
||||
TenantHelper.setTenantId(tenantHeader);
|
||||
}
|
||||
} else {
|
||||
if(login){
|
||||
String tenantId = LoginHelper.getTenantId();
|
||||
if(tenantId == null){
|
||||
ServletUtils.renderString(response, JSONUtil.toJsonStr(R.fail("平台错误")));
|
||||
return;
|
||||
}
|
||||
TenantHelper.setTenantId(tenantId);
|
||||
}
|
||||
}
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
} finally {
|
||||
TenantHelper.clearTenant();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package com.ruoyi.component.tenant.handle;
|
||||
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
|
||||
import com.ruoyi.component.core.exception.ServiceException;
|
||||
import com.ruoyi.component.core.util.StringUtils;
|
||||
import com.ruoyi.component.tenant.helper.TenantHelper;
|
||||
import com.ruoyi.component.tenant.properties.TenantProperties;
|
||||
@@ -29,7 +30,8 @@ public class PlusTenantLineHandler implements TenantLineHandler {
|
||||
String tenantId = TenantHelper.getTenantId();
|
||||
if (StringUtils.isBlank(tenantId)) {
|
||||
log.error("无法获取有效的租户id -> Null");
|
||||
return new NullValue();
|
||||
throw new ServiceException("无法获取有效的平台");
|
||||
// return new NullValue();
|
||||
}
|
||||
// 返回固定租户
|
||||
return new StringValue(tenantId);
|
||||
@@ -37,20 +39,15 @@ public class PlusTenantLineHandler implements TenantLineHandler {
|
||||
|
||||
@Override
|
||||
public boolean ignoreTable(String tableName) {
|
||||
String tenantId = TenantHelper.getTenantId();
|
||||
// 判断是否有租户
|
||||
if (StringUtils.isNotBlank(tenantId)) {
|
||||
// 不需要过滤租户的表
|
||||
List<String> excludes = tenantProperties.getExcludes();
|
||||
// 非业务表
|
||||
List<String> tables = ListUtil.toList(
|
||||
"gen_table",
|
||||
"gen_table_column"
|
||||
);
|
||||
tables.addAll(excludes);
|
||||
return tables.contains(tableName);
|
||||
}
|
||||
return true;
|
||||
// 不需要过滤租户的表
|
||||
List<String> excludes = tenantProperties.getExcludes();
|
||||
// 非业务表
|
||||
List<String> tables = ListUtil.toList(
|
||||
"gen_table",
|
||||
"gen_table_column"
|
||||
);
|
||||
tables.addAll(excludes);
|
||||
return tables.contains(tableName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.ruoyi.component.tenant.handle;
|
||||
|
||||
import com.ruoyi.component.core.constant.GlobalConstants;
|
||||
import com.ruoyi.component.core.exception.ServiceException;
|
||||
import com.ruoyi.component.core.util.StringUtils;
|
||||
import com.ruoyi.component.redis.handler.KeyPrefixHandler;
|
||||
import com.ruoyi.component.tenant.helper.TenantHelper;
|
||||
@@ -32,6 +33,7 @@ public class TenantKeyPrefixHandler extends KeyPrefixHandler {
|
||||
String tenantId = TenantHelper.getTenantId();
|
||||
if (StringUtils.isBlank(tenantId)) {
|
||||
log.error("无法获取有效的租户id -> Null");
|
||||
throw new ServiceException("无法获取有效的平台");
|
||||
}
|
||||
if (StringUtils.startsWith(name, tenantId + "")) {
|
||||
// 如果存在则直接返回
|
||||
@@ -55,6 +57,7 @@ public class TenantKeyPrefixHandler extends KeyPrefixHandler {
|
||||
String tenantId = TenantHelper.getTenantId();
|
||||
if (StringUtils.isBlank(tenantId)) {
|
||||
log.error("无法获取有效的租户id -> Null");
|
||||
throw new ServiceException("无法获取有效的平台");
|
||||
}
|
||||
if (StringUtils.startsWith(unmap, tenantId + "")) {
|
||||
// 如果存在则删除
|
||||
|
||||
@@ -6,11 +6,10 @@ import cn.hutool.core.convert.Convert;
|
||||
import com.alibaba.ttl.TransmittableThreadLocal;
|
||||
import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy;
|
||||
import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
|
||||
import com.ruoyi.component.satoken.utils.LoginHelper;
|
||||
import com.ruoyi.component.core.constant.GlobalConstants;
|
||||
import com.ruoyi.component.core.util.StringUtils;
|
||||
import com.ruoyi.component.core.util.spring.SpringUtils;
|
||||
import com.ruoyi.component.redis.util.RedisUtils;
|
||||
import com.ruoyi.component.satoken.utils.LoginHelper;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -26,10 +25,7 @@ import java.util.function.Supplier;
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class TenantHelper {
|
||||
|
||||
private static final String DYNAMIC_TENANT_KEY = GlobalConstants.GLOBAL_REDIS_KEY + "dynamicTenant";
|
||||
|
||||
private static final ThreadLocal<String> TEMP_DYNAMIC_TENANT = new TransmittableThreadLocal<>();
|
||||
|
||||
private static final ThreadLocal<String> DYNAMIC_TENANT = new TransmittableThreadLocal<>();
|
||||
/**
|
||||
* 租户功能是否启用
|
||||
*/
|
||||
@@ -79,22 +75,11 @@ public class TenantHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置动态租户(一直有效 需要手动清理)
|
||||
* <p>
|
||||
* 如果为未登录状态下 那么只在当前线程内生效
|
||||
*/
|
||||
public static void setDynamic(String tenantId) {
|
||||
public static void setTenantId(String tenantId) {
|
||||
if (!isEnable()) {
|
||||
return;
|
||||
}
|
||||
if (!isLogin()) {
|
||||
TEMP_DYNAMIC_TENANT.set(tenantId);
|
||||
return;
|
||||
}
|
||||
String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId();
|
||||
RedisUtils.setCacheObject(cacheKey, tenantId);
|
||||
SaHolder.getStorage().set(cacheKey, tenantId);
|
||||
DYNAMIC_TENANT.set(tenantId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,37 +87,21 @@ public class TenantHelper {
|
||||
* <p>
|
||||
* 如果为未登录状态下 那么只在当前线程内生效
|
||||
*/
|
||||
public static String getDynamic() {
|
||||
public static String getTenantId() {
|
||||
if (!isEnable()) {
|
||||
return null;
|
||||
}
|
||||
if (!isLogin()) {
|
||||
return TEMP_DYNAMIC_TENANT.get();
|
||||
}
|
||||
String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId();
|
||||
String tenantId = (String) SaHolder.getStorage().get(cacheKey);
|
||||
if (StringUtils.isNotBlank(tenantId)) {
|
||||
return tenantId;
|
||||
}
|
||||
tenantId = RedisUtils.getCacheObject(cacheKey);
|
||||
SaHolder.getStorage().set(cacheKey, tenantId);
|
||||
return tenantId;
|
||||
return DYNAMIC_TENANT.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除动态租户
|
||||
*/
|
||||
public static void clearDynamic() {
|
||||
public static void clearTenant() {
|
||||
if (!isEnable()) {
|
||||
return;
|
||||
}
|
||||
if (!isLogin()) {
|
||||
TEMP_DYNAMIC_TENANT.remove();
|
||||
return;
|
||||
}
|
||||
String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId();
|
||||
RedisUtils.deleteObject(cacheKey);
|
||||
SaHolder.getStorage().delete(cacheKey);
|
||||
DYNAMIC_TENANT.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -141,11 +110,11 @@ public class TenantHelper {
|
||||
* @param handle 处理执行方法
|
||||
*/
|
||||
public static void dynamic(String tenantId, Runnable handle) {
|
||||
setDynamic(tenantId);
|
||||
setTenantId(tenantId);
|
||||
try {
|
||||
handle.run();
|
||||
} finally {
|
||||
clearDynamic();
|
||||
clearTenant();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,29 +124,15 @@ public class TenantHelper {
|
||||
* @param handle 处理执行方法
|
||||
*/
|
||||
public static <T> T dynamic(String tenantId, Supplier<T> handle) {
|
||||
setDynamic(tenantId);
|
||||
setTenantId(tenantId);
|
||||
try {
|
||||
return handle.get();
|
||||
} finally {
|
||||
clearDynamic();
|
||||
clearTenant();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前租户id(动态租户优先)
|
||||
*/
|
||||
public static String getTenantId() {
|
||||
if (!isEnable()) {
|
||||
return null;
|
||||
}
|
||||
String tenantId = TenantHelper.getDynamic();
|
||||
if (StringUtils.isBlank(tenantId)) {
|
||||
tenantId = LoginHelper.getTenantId();
|
||||
}
|
||||
return tenantId;
|
||||
}
|
||||
|
||||
private static boolean isLogin() {
|
||||
public static boolean isLogin() {
|
||||
try {
|
||||
StpUtil.checkLogin();
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user