BladeX多租户解决000000除admin的其它角色无法查看所有租户数据问题(mybatis-plus多租户)

需求默认租户下的角色需要看到全部数据,直接上代码

实现TenantLineHandler接口重写方法

package org.springblade.common.config;

import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tenant.BladeTenantHolder;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @Author: chenl
 * @Date: 2024/7/24
 */
public class MyTenantLineHandler implements TenantLineHandler {

	/**
	 * 需要排除进行自定义的多租户表
	 */
	private final List<String> excludeTableList = Arrays.asList("blade_user", "blade_dept", "blade_role", "blade_tenant", "act_de_model");
	/**
	 * 匹配的多租户表
	 */
	private final Set<String> tenantTableList = new HashSet<>();

	@Override
	public Expression getTenantId() {
	     // 另一种写法,可以实现模糊查询多个租户,但是我这里不需要
		// LikeExpression likeExpression = new LikeExpression();
		// likeExpression.withRightExpression(new StringValue("%" + "000000" + "%"));
		// return likeExpression;
		// 坑:AuthUtil.getTenantId()在登录是是空字符串,Func.toStr无法识别
		String tenantId = Func.toStr(AuthUtil.getTenantId().isEmpty() ?null:AuthUtil.getTenantId(), BladeConstant.ADMIN_TENANT_ID);;
		return new StringValue(tenantId);
	}

	@Override
	public String getTenantIdColumn() {
		return "tenant_id";
	}


	/**
	 * 根据表名判断是否忽略拼接多租户条件
	 * 默认都要进行解析并拼接多租户条件
	 *
	 * @param tableName 表名
	 * @return 是否忽略, true:表示忽略,false:需要解析并拼接多租户条件
	 */
	@Override
	public boolean ignoreTable(String tableName) {
		if (BladeTenantHolder.isIgnore()) {
			return true;
		}
		// 添加需要排除的表,表里没有租户id的,更加具体环境,BladeConstant.ADMIN_TENANT_ID就是枚举默认值000000
		tenantTableList.add("blade_dict");
		tenantTableList.add("blade_menu");
		tenantTableList.add("blade_role_menu");
		tenantTableList.add("blade_tenant_package");
		tenantTableList.add("blade_user_web");
		String tenantId = Func.toStr(AuthUtil.getTenantId().isEmpty() ?null:AuthUtil.getTenantId(), BladeConstant.ADMIN_TENANT_ID);
		boolean result = tenantTableList.contains(tableName) && StringUtil.isNotBlank(tenantId);
		return result;
	}

}

继承TenantLineInnerInterceptor重写如下方法

package org.springblade.common.config;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.schema.Table;
import org.springblade.core.secure.utils.AuthUtil;

import java.util.Arrays;
import java.util.List;

/**
 * @Author: chenl
 * @Date: 2024/7/24
 */
public class MyTenantLineInnerInterceptor extends TenantLineInnerInterceptor {
	private MyTenantLineHandler tenantLineHandler;

	/**
	 * 超管需要启用租户过滤的表
	 */
	private List<String> adminTenantTables = Arrays.asList("blade_top_menu", "blade_dict_biz");

	public TenantLineHandler getTenantLineHandler() {
		return this.tenantLineHandler;
	}

	public void setTenantLineHandler(final MyTenantLineHandler tenantLineHandler) {
		this.tenantLineHandler = tenantLineHandler;
	}

	public MyTenantLineInnerInterceptor() {
	}

	public MyTenantLineInnerInterceptor(final MyTenantLineHandler tenantLineHandler) {
		super.setTenantLineHandler(tenantLineHandler);
		this.tenantLineHandler = tenantLineHandler;
	}

	@Override
	public Expression buildTableExpression(Table table, Expression where, String whereSegment) {
			
		//若是忽略的表则不进行数据隔离
		if (this.tenantLineHandler.ignoreTable(table.getName())) {
			return null;
		}
		//若是超管则不进行数据隔离
		if (doTenantFilter(table.getName())) {
			return null;
		}
		// 默认租户可以查看所有数据(自定义,上面两个是bladex原逻辑)
		if(ObjectUtil.contains(this.tenantLineHandler.getTenantId().toString(),"000000")){
			return null;
		}
		//获得条件表达式
		return new EqualsTo(getAliasColumn(table), this.tenantLineHandler.getTenantId());
		// 模糊查询使用的逻辑,我不需要
		// if (this.tenantLineHandler.ignoreTable(table.getName())) {
		// 	return null;
		// }
		// Expression expression = this.tenantLineHandler.getTenantId();
		// LikeExpression likeExpression = null;
		// if (expression instanceof LikeExpression) {
		// 	likeExpression = (LikeExpression) expression;
		// 	likeExpression.withLeftExpression(this.getAliasColumn(table));
		// }
		// return likeExpression;
	}

	// protected Column getAliasColumn(Table table) {
	// 	StringBuilder column = new StringBuilder();
	// 	if (table.getAlias() != null) {
	// 		column.append(table.getAlias().getName()).append(".");
	// 	}
	//
	// 	column.append(this.tenantLineHandler.getTenantIdColumn());
	// 	return new Column(column.toString());
	// }

	/**
	 * 判断当前操作是否需要进行过滤
	 *
	 * @param tableName 表名
	 */
	public boolean doTenantFilter(String tableName) {
		return AuthUtil.isAdministrator() && !adminTenantTables.contains(tableName);
	}

	/**
	 * 判断当前操作是否需要进行过滤
	 *
	 * @param tables 表名
	 */
	// public boolean doTenantFilters(List<Table> tables) {
	// 	List<String> tableNames = tables.stream().map(Table::getName).collect(Collectors.toList());
	// 	return AuthUtil.isAdministrator() && !CollectionUtil.containsAny(adminTenantTables, tableNames);
	// }
}

再配置类里添加自定义的注入,任意配置类

/**
 * BladeX Commercial License Agreement
 * Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
 * <p>
 * Use of this software is governed by the Commercial License Agreement
 * obtained after purchasing a license from BladeX.
 * <p>
 * 1. This software is for development use only under a valid license
 * from BladeX.
 * <p>
 * 2. Redistribution of this software's source code to any third party
 * without a commercial license is strictly prohibited.
 * <p>
 * 3. Licensees may copyright their own code but cannot use segments
 * from this software for such purposes. Copyright of this software
 * remains with BladeX.
 * <p>
 * Using this software signifies agreement to this License, and the software
 * must not be used for illegal purposes.
 * <p>
 * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
 * not liable for any claims arising from secondary or illegal development.
 * <p>
 * Author: Chill Zhuang (bladejava@qq.com)
 */
package org.springblade.common.config;


import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import org.springblade.core.launch.constant.AppConstant;
import org.springblade.core.oauth2.endpoint.OAuth2SocialEndpoint;
import org.springblade.core.oauth2.endpoint.OAuth2TokenEndPoint;
import org.springblade.core.secure.registry.SecureRegistry;
import org.springblade.core.tool.utils.StringPool;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * Blade配置
 *
 * @author Chill
 */
@Configuration(proxyBeanMethods = false)
public class BladeConfiguration implements WebMvcConfigurer {

	/**
	 * 安全框架配置
	 */
	@Bean
	public SecureRegistry secureRegistry() {
		SecureRegistry secureRegistry = new SecureRegistry();
		secureRegistry.setEnabled(true);
		secureRegistry.excludePathPatterns("/blade-auth/**");
		secureRegistry.excludePathPatterns("/blade-system/tenant/info");
		secureRegistry.excludePathPatterns("/blade-system/tenant/list");
		secureRegistry.excludePathPatterns("/blade-system/tenant/register");
		secureRegistry.excludePathPatterns("/blade-system/tenant/checkCaptchaTenant");
		secureRegistry.excludePathPatterns("/blade-flow/process/resource-view");
		secureRegistry.excludePathPatterns("/blade-flow/process/diagram-view");
		secureRegistry.excludePathPatterns("/blade-flow/manager/check-upload");
		secureRegistry.excludePathPatterns("/doc.html");
		secureRegistry.excludePathPatterns("/swagger-ui.html");
		secureRegistry.excludePathPatterns("/static/**");
		secureRegistry.excludePathPatterns("/webjars/**");
		secureRegistry.excludePathPatterns("/swagger-resources/**");
		secureRegistry.excludePathPatterns("/druid/**");
		secureRegistry.excludePathPatterns("/blade-system/region/**");
		return secureRegistry;
	}

	/**
	 * 跨域配置
	 */
	@Override
	public void addCorsMappings(CorsRegistry registry) {
		registry.addMapping("/cors/**")
			.allowedOriginPatterns("*")
			.allowedHeaders("*")
			.allowedMethods("*")
			.maxAge(3600)
			.allowCredentials(true);
	}

	/**
	 * 给OAuth2服务端添加前缀
	 */
	@Override
	public void configurePathMatch(PathMatchConfigurer configurer) {
		configurer.addPathPrefix(StringPool.SLASH + AppConstant.APPLICATION_AUTH_NAME,
			c -> c.isAnnotationPresent(RestController.class) && (
				OAuth2TokenEndPoint.class.equals(c) || OAuth2SocialEndpoint.class.equals(c))
		);
	}

    // 主要这个,注入我们自定义的bean
	@Bean
	public MybatisPlusInterceptor mybatisPlusInterceptor() {
		MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
		// 保留分页插件,不然无法分页
		interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
		interceptor.addInnerInterceptor(new MyTenantLineInnerInterceptor(new MyTenantLineHandler()));
		return interceptor;
	}


}

结束,参考文章:添加链接描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值