移植 multi-tenant
diff --git a/build.gradle b/build.gradle
index d863f07..8b61a61 100644
--- a/build.gradle
+++ b/build.gradle
@@ -102,7 +102,7 @@
springSocialVersion = '1.1.6.RELEASE'
springKafkaVersion = '2.2.8.RELEASE'
postgresVersion = '42.2.5'
- multiTenantLibVersion = '1.0.8'
+ multiTenantLibVersion = '1.1.3'
}
implementation "org.jetbrains.kotlin:kotlin-reflect"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/core/DayendSettleTask.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/core/DayendSettleTask.java
index 37f30ea..1eb9422 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/core/DayendSettleTask.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/core/DayendSettleTask.java
@@ -5,6 +5,7 @@
import com.supwisdom.dlpay.framework.service.DayendSettleService;
import com.supwisdom.dlpay.framework.util.Constants;
import com.supwisdom.dlpay.framework.util.StringUtil;
+import com.supwisdom.multitenant.TenantContextHolder;
import com.supwisdom.multitenant.TenantDetailsProvider;
import net.javacrumbs.shedlock.core.SchedulerLock;
import org.slf4j.Logger;
@@ -28,7 +29,7 @@
@SchedulerLock(name = "DayendSettleTask", lockAtMostForString = "PT30M")
public void doSettleTask() {
if (logger.isDebugEnabled()) logger.debug("进入日结算任务!");
- tenantDetailsProvider.defaultTenant(Constants.DEFAULT_TENANTID);
+ TenantContextHolder.getContext().setTenant(tenantDetailsProvider.defaultTenant());
settleLog = dayendSettleService.doCreateSettleLog(); //记录日志
try {
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/filter/CrosXssFilter.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/filter/CrosXssFilter.java
index 632ffde..ebe49e4 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/filter/CrosXssFilter.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/filter/CrosXssFilter.java
@@ -1,18 +1,12 @@
package com.supwisdom.dlpay.framework.filter;
-import com.google.gson.Gson;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter
public class CrosXssFilter implements Filter {
- private static final Logger logger = LoggerFactory.getLogger(CrosXssFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
@@ -21,31 +15,11 @@
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
- request.setCharacterEncoding("utf-8");
-
- //跨域设置
-// if(response instanceof HttpServletResponse){
-// HttpServletResponse httpServletResponse=(HttpServletResponse)response;
-// //通过在响应 header 中设置 ‘*’ 来允许来自所有域的跨域请求访问。
-// httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
-// //通过对 Credentials 参数的设置,就可以保持跨域 Ajax 时的 Cookie
-// //设置了Allow-Credentials,Allow-Origin就不能为*,需要指明具体的url域
-// //httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
-// //请求方式
-// httpServletResponse.setHeader("Access-Control-Allow-Methods", "*");
-// //(预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 可以被缓存多久
-// httpServletResponse.setHeader("Access-Control-Max-Age", "86400");
-// //首部字段用于预检请求的响应。其指明了实际请求中允许携带的首部字段
-// httpServletResponse.setHeader("Access-Control-Allow-Headers", "*");
-// }
-
//sql,xss过滤
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
-// logger.info("CrosXssFilter.......orignal url:{},ParameterMap:{}", httpServletRequest.getRequestURI(), new Gson().toJson(httpServletRequest.getParameterMap()));
XssHttpServletRequestWrapper xssHttpServletRequestWrapper = new XssHttpServletRequestWrapper(
httpServletRequest);
chain.doFilter(xssHttpServletRequestWrapper, response);
-// logger.info("CrosXssFilter..........doFilter url:{},ParameterMap:{}", xssHttpServletRequestWrapper.getRequestURI(), new Gson().toJson(xssHttpServletRequestWrapper.getParameterMap()));
}
@Override
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/filter/ValidateCodeFilter.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/filter/ValidateCodeFilter.java
index c58260d..e234066 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/filter/ValidateCodeFilter.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/filter/ValidateCodeFilter.java
@@ -49,10 +49,6 @@
try {
validate(request);
} catch (ValidateCodeException e) {
- //response.setStatus(HttpStatus.OK.value());
- //response.setContentType("application/json;charset=UTF-8");
- //response.getWriter().write(objectMapper.writeValueAsString(JsonResult.error(400, e.getMessage())));
- //response.sendError(HttpStatus.UNAUTHORIZED.value(),e.getMessage());
myAuthenticationFailureHandler.onAuthenticationFailure(request, response, e);
return;
}
@@ -66,27 +62,6 @@
} else {
request.getSession().removeAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
}
-// VerifyCode imageCode = (VerifyCode) request.getSession().getAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY);
-// String inputCode;
-// try {
-// inputCode = request.getParameter("imageCode");
-// } catch (Exception e) {
-// throw new ValidateCodeException("获取验证码的值失败");
-// }
-// if (StringUtil.isEmpty(inputCode)) {
-// throw new ValidateCodeException("验证码不能为空");
-// }
-// if (null == imageCode) {
-// throw new ValidateCodeException("验证码不存在");
-// }
-// if (imageCode.isExpired()) {
-// request.getSession().removeAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY);
-// throw new ValidateCodeException("验证码已过期");
-// }
-// if (!StringUtil.equalsIgnoreCase(imageCode.getText(), inputCode)) {
-// throw new ValidateCodeException("验证码不匹配");
-// }
-// request.getSession().removeAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY);
}
}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/security/MyAuthenticationSuccessHandler.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/security/MyAuthenticationSuccessHandler.java
index abaa46a..f74d15d 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/security/MyAuthenticationSuccessHandler.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/security/MyAuthenticationSuccessHandler.java
@@ -5,7 +5,6 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
-import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/service/impl/OperatorDetailServiceImpl.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/service/impl/OperatorDetailServiceImpl.java
index 755828d..88f2121 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/service/impl/OperatorDetailServiceImpl.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/service/impl/OperatorDetailServiceImpl.java
@@ -5,7 +5,9 @@
import com.supwisdom.dlpay.framework.domain.TOperator;
import com.supwisdom.dlpay.framework.service.OperatorDetailService;
import com.supwisdom.dlpay.framework.util.StringUtil;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.supwisdom.multitenant.TenantDetails;
+import com.supwisdom.multitenant.TenantSessionHelper;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
@@ -16,16 +18,30 @@
import java.util.Collection;
import java.util.List;
+import static org.apache.commons.lang3.StringUtils.substringAfter;
+import static org.apache.commons.lang3.StringUtils.substringBefore;
+
+
+@Slf4j
@Service
public class OperatorDetailServiceImpl implements OperatorDetailService {
- @Autowired
- private OperatorDao operatorDao;
- @Autowired
- private OperRoleDao operRoleDao;
+ private final OperatorDao operatorDao;
+ private final OperRoleDao operRoleDao;
+ private final TenantSessionHelper tenantSessionHelper;
+
+ public OperatorDetailServiceImpl(OperatorDao operatorDao, OperRoleDao operRoleDao,
+ TenantSessionHelper tenantSessionHelper) {
+ this.operatorDao = operatorDao;
+ this.operRoleDao = operRoleDao;
+ this.tenantSessionHelper = tenantSessionHelper;
+ }
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
- TOperator oper = operatorDao.findByOpercode(username);
+ String domain = substringAfter(username, "@");
+ tenantSessionHelper.setSessionTenantById(domain);
+ String realname = substringBefore(username, "@");
+ TOperator oper = operatorDao.findByOpercode(realname);
if (null == oper) {
throw new UsernameNotFoundException("管理员不存在");
}
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
index a422391..4b88ed0 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
@@ -5,6 +5,7 @@
import com.supwisdom.dlpay.framework.util.Constants
import com.supwisdom.multitenant.TenantDetails
import com.supwisdom.multitenant.TenantDetailsProvider
+import com.supwisdom.multitenant.TenantSessionData
import com.supwisdom.multitenant.annotations.EnableHttpHeaderTenantInterceptor
import com.supwisdom.multitenant.annotations.EnableSessionTenantInterceptor
import io.lettuce.core.ReadFrom
@@ -178,6 +179,10 @@
dataCenter = "default"
}
+ override fun defaultTenant(): TenantDetails {
+ return defaultTenant
+ }
+
override fun createDetailsById(id: String?): TenantDetails {
return tenantService.findByTenantId(id)?.let { catalog ->
TenantDetails().apply {
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/notify_api_controller.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/notify_api_controller.kt
index e578794..8b38238 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/notify_api_controller.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/notify_api_controller.kt
@@ -36,7 +36,7 @@
fun index(@PathVariable schema: String, request: HttpServletRequest,
response: HttpServletResponse): String {
logger.error("====================== 收到微信回调通知 wechat notify: ========================")
- tenantDetailsProvider.defaultTenant(schema)
+ TenantContextHolder.getContext().tenant = tenantDetailsProvider.createDetailsById(schema)
try {
// 解析结果存储在HashMap
var map: MutableMap<String, String> = HashMap()
@@ -47,7 +47,7 @@
// 得到xml根元素
val root = document.rootElement
// 得到根元素的所有子节点
- val elementList = root.elements() as MutableList<Element>
+ val elementList = root.elements() as MutableList<Element>
// 遍历所有子节点
for (e in elementList) {
map[e.name] = e.text
@@ -90,7 +90,7 @@
fun alipay(@PathVariable schema: String, request: HttpServletRequest,
response: HttpServletResponse): String {
logger.error("====================== 收到支付宝回调通知 alipay notify: ========================")
- tenantDetailsProvider.defaultTenant(schema)
+ TenantContextHolder.getContext().tenant = tenantDetailsProvider.createDetailsById(schema)
// 解析结果存储在HashMap
val map = makeMapFromParam(request)
val resp = alipayService.doNotify(map)
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_sourcetype_chk.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_sourcetype_chk.kt
index 33d9a72..e3ab9e4 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_sourcetype_chk.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/scheduler_sourcetype_chk.kt
@@ -14,6 +14,7 @@
import com.supwisdom.dlpay.framework.util.Constants
import com.supwisdom.dlpay.framework.util.DateUtil
import com.supwisdom.dlpay.util.ConstantUtil
+import com.supwisdom.multitenant.TenantContextHolder
import com.supwisdom.multitenant.TenantDetailsProvider
import mu.KotlinLogging
import net.javacrumbs.shedlock.core.SchedulerLock
@@ -162,7 +163,7 @@
@Scheduled(cron = "\${payapi.sourcetype.checker.scheduler:-}")
@SchedulerLock(name = "payapiSourceTypeCheckLock", lockAtMostForString = "PT30M")
fun runCheck() {
- tenantDetailsProvider.defaultTenant(Constants.DEFAULT_TENANTID)
+ TenantContextHolder.getContext().tenant = tenantDetailsProvider.defaultTenant()
val allSourcetype = sourceTypeService.allEnabledSourcetype
?: return
@@ -276,7 +277,7 @@
fun checkAndDownloadChkfile(checkStatus: TSourceTypeCheckStatus): Future<ExecutorResult> {
// 2. 根据对账日期下载对账文件
try {
- tenantDetailsProvider.defaultTenant(Constants.DEFAULT_TENANTID)
+ TenantContextHolder.getContext().tenant = tenantDetailsProvider.defaultTenant()
if (checkStatus.settleStatus) {
return AsyncResult(ExecutorResult(checkStatus, FAIL, "[${checkStatus.checkAccdate}]日对账已完成"))
}
@@ -319,7 +320,7 @@
@Async("sourcetypeCheckTaskExecutor")
fun reconciliation(checkStatus: TSourceTypeCheckStatus): Future<ExecutorResult> {
// 3. 完成对账
- tenantDetailsProvider.defaultTenant(Constants.DEFAULT_TENANTID)
+ TenantContextHolder.getContext().tenant = tenantDetailsProvider.defaultTenant()
if (!checkStatus.checkFileOk) {
return AsyncResult(ExecutorResult(checkStatus, FAIL, "checkAccdate=[${checkStatus.checkAccdate}]对账单未完成下载,不能对账"))
} else if (checkStatus.settleStatus) {
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt
index ed5783f..deabb41 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt
@@ -21,16 +21,13 @@
import com.supwisdom.dlpay.framework.util.*
import com.supwisdom.dlpay.system.service.FunctionService
import mu.KotlinLogging
-import org.jose4j.jwt.ReservedClaimNames
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.redis.connection.RedisConnectionFactory
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
-import org.springframework.security.core.Authentication
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.core.userdetails.UserDetails
-import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper
import org.springframework.security.oauth2.provider.OAuth2Authentication
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler
@@ -40,7 +37,6 @@
import org.springframework.web.bind.annotation.*
import org.springframework.web.context.request.ServletWebRequest
import java.io.IOException
-import java.security.Principal
import java.util.*
import javax.imageio.ImageIO
import javax.servlet.http.HttpServletRequest
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/tenant.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/tenant.kt
deleted file mode 100644
index b9b6034..0000000
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/tenant.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.supwisdom.dlpay.framework
-
-import mu.KotlinLogging
-import org.springframework.beans.factory.annotation.Autowired
-import org.springframework.context.annotation.Configuration
-import org.springframework.web.servlet.config.annotation.InterceptorRegistry
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
-import javax.annotation.PostConstruct
-
-
-//@Order(1)
-//@WebFilter(filterName = "multi_tenant_filter", urlPatterns = ["/*"])
-//class TenantNameFilter : Filter {
-// override fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
-// if (request is HttpServletRequest) {
-// request.getHeader(Constants.HEADER_TETANTID)?.also {
-// // set tanent datasource
-// TenantContext.setTenantSchema(it)
-// } ?: TenantContext.setTenantSchema("default")
-// }
-// chain.doFilter(request, response)
-// }
-//}
-
-//@Configuration
-//class MultiTenantDatasourceConfiguration : WebMvcConfigurer {
-//
-// private val logger = KotlinLogging.logger { }
-// @Autowired
-// private lateinit var tenantInterceptor: TenantInterceptor
-//
-// @PostConstruct
-// fun post() {
-// logger.info("MultiTenantDatasourceConfiguration post constructor.")
-// }
-//
-// override fun addInterceptors(registry: InterceptorRegistry) {
-// logger.info("adding interceptor(s).")
-// registry.addInterceptor(tenantInterceptor)
-// }
-//}
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/security.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/security.kt
index ee4a5c6..61c805f 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/security.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/security.kt
@@ -231,6 +231,7 @@
class ApiWebSecurityConfigurationAdapter : WebSecurityConfigurerAdapter() {
@Autowired
lateinit var apiJwtAuthenticationFilter: ApiJwtAuthenticationFilter
+
override fun configure(http: HttpSecurity) {
// 设置 API 访问权限管理
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
@@ -374,14 +375,14 @@
http.apply(validateCodeSecurityConfig)
.and()
.authorizeRequests()
- .antMatchers("/login", "/login/form", "/mobileapi/**","/userinfor").permitAll()
+ .antMatchers("/login", "/login/form", "/mobileapi/**", "/userinfor").permitAll()
.antMatchers("/static/**").permitAll()
.antMatchers("/code/image").permitAll()
.antMatchers("/**").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated()
.and()
.sessionManagement()
- .sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
+ .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.formLogin()
.loginPage("/login")
diff --git a/payapi/src/main/resources/application.properties b/payapi/src/main/resources/application.properties
index 8627bf0..906a5be 100644
--- a/payapi/src/main/resources/application.properties
+++ b/payapi/src/main/resources/application.properties
@@ -42,5 +42,6 @@
spring.redis.database=0
###################################################
multi-tenant.header.key=X-TENANT-ID
-multi-tenant.session.name=multi-tenant-id
+multi-tenant.session.name=tenant-id
+multi-tenant.session.enableSessionScopedBean=false
multi-tenant.dbschema=public