|
@@ -1,114 +0,0 @@
|
|
|
-package com.usky.common.tenant.core.security;
|
|
|
-
|
|
|
-import cn.hutool.core.collection.CollUtil;
|
|
|
-import cn.hutool.core.collection.CollectionUtil;
|
|
|
-import com.alibaba.fastjson.JSON;
|
|
|
-import com.usky.common.core.bean.ApiResult;
|
|
|
-import com.usky.common.core.exception.BusinessException;
|
|
|
-import com.usky.common.core.util.ServletUtils;
|
|
|
-import com.usky.common.security.utils.SecurityUtils;
|
|
|
-import com.usky.common.tenant.config.TenantProperties;
|
|
|
-import com.usky.common.tenant.core.context.TenantContextHolder;
|
|
|
-import com.usky.common.tenant.core.service.TenantFrameworkService;
|
|
|
-import com.usky.system.model.LoginUser;
|
|
|
-import lombok.extern.slf4j.Slf4j;
|
|
|
-import org.springframework.http.HttpStatus;
|
|
|
-import org.springframework.util.AntPathMatcher;
|
|
|
-import org.springframework.web.filter.OncePerRequestFilter;
|
|
|
-
|
|
|
-import javax.servlet.FilterChain;
|
|
|
-import javax.servlet.ServletException;
|
|
|
-import javax.servlet.http.HttpServletRequest;
|
|
|
-import javax.servlet.http.HttpServletResponse;
|
|
|
-import java.io.IOException;
|
|
|
-import java.util.Objects;
|
|
|
-
|
|
|
-/**
|
|
|
- * 多租户 Security Web 过滤器
|
|
|
- * 1. 如果是登陆的用户,校验是否有权限访问该租户,避免越权问题。
|
|
|
- * 2. 如果请求未带租户的编号,检查是否是忽略的 URL,否则也不允许访问。
|
|
|
- * 3. 校验租户是合法,例如说被禁用、到期
|
|
|
- *
|
|
|
- * 校验用户访问的租户,是否是其所在的租户,
|
|
|
- *
|
|
|
- * @author yq
|
|
|
- */
|
|
|
-@Slf4j
|
|
|
-public class TenantSecurityWebFilter extends OncePerRequestFilter {
|
|
|
-
|
|
|
- private final TenantProperties tenantProperties;
|
|
|
-
|
|
|
- private final AntPathMatcher pathMatcher;
|
|
|
-
|
|
|
- private final TenantFrameworkService tenantFrameworkService;
|
|
|
-
|
|
|
- public TenantSecurityWebFilter(TenantProperties tenantProperties,
|
|
|
- TenantFrameworkService tenantFrameworkService) {
|
|
|
- this.tenantProperties = tenantProperties;
|
|
|
- this.pathMatcher = new AntPathMatcher();
|
|
|
- this.tenantFrameworkService = tenantFrameworkService;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
|
|
- throws ServletException, IOException {
|
|
|
- Integer tenantId = TenantContextHolder.getTenantId();
|
|
|
- // 1. 登陆的用户,校验是否有权限访问该租户,避免越权问题。
|
|
|
- LoginUser user = SecurityUtils.getLoginUser();
|
|
|
- if (user != null) {
|
|
|
- // 如果获取不到租户编号,则尝试使用登陆用户的租户编号
|
|
|
- if (tenantId == null) {
|
|
|
- tenantId = user.getTenantId();
|
|
|
- TenantContextHolder.setTenantId(tenantId);
|
|
|
- // 如果传递了租户编号,则进行比对租户编号,避免越权问题
|
|
|
- } else if (!Objects.equals(user.getTenantId(), TenantContextHolder.getTenantId())) {
|
|
|
- String msg = "您无权访问该租户的数据";
|
|
|
- ServletUtils.renderString(response, JSON.toJSONString(ApiResult.error(String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()), msg)));
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 如果非允许忽略租户的 URL,则校验租户是否合法
|
|
|
- if (!isIgnoreUrl(request)) {
|
|
|
- // 2. 如果请求未带租户的编号,不允许访问。
|
|
|
- if (tenantId == null) {
|
|
|
- String msg = "租户的请求未传递,请进行排查";
|
|
|
- ServletUtils.renderString(response, JSON.toJSONString(ApiResult.error(String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()), msg)));
|
|
|
- return;
|
|
|
- }
|
|
|
- // 3. 校验租户是合法,例如说被禁用、到期
|
|
|
- try {
|
|
|
- tenantFrameworkService.validTenant(tenantId);
|
|
|
- } catch (Throwable ex) {
|
|
|
- BusinessException businessException = (BusinessException)ex.getCause();
|
|
|
- String msg = businessException.getCustomMessage();
|
|
|
- ServletUtils.renderString(response, JSON.toJSONString(ApiResult.error(String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value()), msg)));
|
|
|
- return;
|
|
|
- }
|
|
|
- } else { // 如果是允许忽略租户的 URL,若未传递租户编号,则默认忽略租户编号,避免报错
|
|
|
- if (tenantId == null) {
|
|
|
- TenantContextHolder.setIgnore(true);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 继续过滤
|
|
|
- chain.doFilter(request, response);
|
|
|
- }
|
|
|
-
|
|
|
- private boolean isIgnoreUrl(HttpServletRequest request) {
|
|
|
- if (CollectionUtil.isNotEmpty(tenantProperties.getIgnoreUrls())){
|
|
|
- // 快速匹配,保证性能
|
|
|
- if (CollUtil.contains(tenantProperties.getIgnoreUrls(), request.getRequestURI())) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- // 逐个 Ant 路径匹配
|
|
|
- for (String url : tenantProperties.getIgnoreUrls()) {
|
|
|
- if (pathMatcher.match(url, request.getRequestURI())) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
-}
|