diff --git a/kicc-common/kicc-common-data/src/main/java/com/cloud/kicc/common/data/handler/KiccTenantLineHandler.java b/kicc-common/kicc-common-data/src/main/java/com/cloud/kicc/common/data/handler/KiccTenantLineHandler.java index e2d52a0e..27705db3 100644 --- a/kicc-common/kicc-common-data/src/main/java/com/cloud/kicc/common/data/handler/KiccTenantLineHandler.java +++ b/kicc-common/kicc-common-data/src/main/java/com/cloud/kicc/common/data/handler/KiccTenantLineHandler.java @@ -1,12 +1,10 @@ package com.cloud.kicc.common.data.handler; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler; import com.cloud.kicc.common.data.entity.KiccUser; import com.cloud.kicc.common.data.override.TenantLikeExpression; import com.cloud.kicc.common.data.properties.TenantProperties; -import com.cloud.kicc.common.data.util.TenantContextHolder; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.schema.Column; import org.springframework.security.core.Authentication; @@ -59,7 +57,21 @@ public class KiccTenantLineHandler implements TenantLineHandler { @Override public Expression getTenantId() { // 返回当前用户所属的多租户ID进行条件拼接 - return StrUtil.isNotBlank(TenantContextHolder.getTenant()) ? new TenantLikeExpression(TenantContextHolder.getTenant()): null; + return ObjectUtil.isNotEmpty(getUser()) ? new TenantLikeExpression(getUser().getTenantId()): null; + } + + /** + * 获取用户 + */ + protected KiccUser getUser() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (Optional.ofNullable(authentication).isPresent()) { + Object principal = authentication.getPrincipal(); + if (principal instanceof KiccUser) { + return (KiccUser) principal; + } + } + return null; } } diff --git a/kicc-common/kicc-common-data/src/main/java/com/cloud/kicc/common/data/util/TenantContextHolder.java b/kicc-common/kicc-common-data/src/main/java/com/cloud/kicc/common/data/util/TenantContextHolder.java deleted file mode 100644 index 72ad129b..00000000 --- a/kicc-common/kicc-common-data/src/main/java/com/cloud/kicc/common/data/util/TenantContextHolder.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.cloud.kicc.common.data.util; - -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import com.cloud.kicc.common.data.entity.KiccUser; -import com.cloud.kicc.common.data.override.TenantLikeExpression; -import lombok.experimental.UtilityClass; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; - -import java.util.Optional; -import java.util.concurrent.atomic.AtomicReference; - -/** - *

- * 动态设置多租户 - *

- * - * @Author: entfrm开发团队-王翔 - * @Date: 2022/5/13 - */ -@UtilityClass -public class TenantContextHolder { - - private final ThreadLocal contextHolder = new ThreadLocal(); - - public void setTenant(String tenantIds) { - contextHolder.set(tenantIds); - } - - public String getTenant() { - String tenantIds = ObjectUtil.isNotEmpty(getUser()) ? getUser().getTenantId() : clearTenant(); - return StrUtil.isNotBlank(contextHolder.get()) ? contextHolder.get() : tenantIds; - } - - /** - * 校验用户多租户是否为空,为空说明当前用户未登录,需要清除当前线程多租户数据 - * 不收的销毁,会出现 ThreadLocal 内存泄漏的问题 - */ - public String clearTenant() { - contextHolder.remove(); - return null; - } - - /** - * 获取用户 - * 如果当前不存在用户,正常情况多租户拼接查询会报错 - */ - private KiccUser getUser() { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (Optional.ofNullable(authentication).isPresent()) { - Object principal = authentication.getPrincipal(); - if (principal instanceof KiccUser) { - return (KiccUser) principal; - } - } - return null; - } - -} diff --git a/kicc-common/kicc-common-security/src/main/java/com/cloud/kicc/common/security/exp/KiccLocalResourceServerTokenServices.java b/kicc-common/kicc-common-security/src/main/java/com/cloud/kicc/common/security/exp/KiccLocalResourceServerTokenServices.java index b44c54a0..2647436e 100644 --- a/kicc-common/kicc-common-security/src/main/java/com/cloud/kicc/common/security/exp/KiccLocalResourceServerTokenServices.java +++ b/kicc-common/kicc-common-security/src/main/java/com/cloud/kicc/common/security/exp/KiccLocalResourceServerTokenServices.java @@ -45,33 +45,14 @@ public class KiccLocalResourceServerTokenServices implements ResourceServerToken } OAuth2Request oAuth2Request = oAuth2Authentication.getOAuth2Request(); + // 检测是否是属于认证的KiccUser实体用户 if (!(oAuth2Authentication.getPrincipal() instanceof KiccUser)) { return oAuth2Authentication; } - String clientId = oAuth2Request.getClientId(); - - // 根据客户端授权类型加载身份验证,考虑多种登录方式,比如手机登录,用户密码登录 - Map userDetailsServiceMap = SpringUtil.getBeansOfType(KiccUserDetailsService.class); - Optional optional = userDetailsServiceMap.values().stream() - .filter(service -> service.support(clientId, oAuth2Request.getGrantType())) - .max(Comparator.comparingInt(Ordered::getOrder)); - - if (!optional.isPresent()) { - throw new InternalAuthenticationServiceException("UserDetailsService error , not register"); - } - - // 根据 username 查询 spring cache 最新的值 并返回 KiccUser kiccUser = (KiccUser) oAuth2Authentication.getPrincipal(); - - UserDetails userDetails; - try { - userDetails = optional.get().loadUserByUser(kiccUser); - } catch (UsernameNotFoundException notFoundException) { - throw new UnauthorizedException(String.format("%s username not found", kiccUser.getUsername()), notFoundException); - } - // 加载用户名密码身份验证令牌 - Authentication userAuthentication = new UsernamePasswordAuthenticationToken(userDetails, "N/A", userDetails.getAuthorities()); + // 每次请求前都预先加载用户名密码身份验证令牌 + Authentication userAuthentication = new UsernamePasswordAuthenticationToken(kiccUser, "N/A", kiccUser.getAuthorities()); OAuth2Authentication authentication = new OAuth2Authentication(oAuth2Request, userAuthentication); authentication.setAuthenticated(true); return authentication; diff --git a/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/controller/UserController.java b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/controller/UserController.java index 163b4333..86be2127 100644 --- a/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/controller/UserController.java +++ b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/controller/UserController.java @@ -9,7 +9,6 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.cloud.kicc.common.core.api.R; import com.cloud.kicc.common.core.constant.AppConstants; import com.cloud.kicc.common.data.entity.KiccUser; -import com.cloud.kicc.common.data.util.TenantContextHolder; import com.cloud.kicc.common.log.annotation.SysLog; import com.cloud.kicc.common.security.annotation.Inner; import com.cloud.kicc.common.security.util.SecurityUtils; @@ -24,6 +23,7 @@ import com.cloud.kicc.system.service.UserService; import com.pig4cloud.plugin.excel.annotation.ResponseExcel; import com.pig4cloud.plugin.excel.annotation.Sheet; import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @@ -206,12 +206,12 @@ public class UserController { return userService.list(); } - + @SneakyThrows @SysLog("用户多租户更改") @GetMapping("/changeTenant/{tenantIds:[\\w,]+}") @PreAuthorize("@pms.hasPermission('user_edit')") public R changeTenant(@PathVariable String[] tenantIds) { - TenantContextHolder.setTenant(StrUtil.join(",", tenantIds)); + userService.setCurrentUserTenant(tenantIds); return R.ok(); } @@ -219,7 +219,8 @@ public class UserController { @GetMapping("/resetTenant") @PreAuthorize("@pms.hasPermission('user_edit')") public R resetTenant() { - TenantContextHolder.setTenant(SecurityUtils.getUser().getTenantId()); + User user = userService.getOne(Wrappers.query().lambda().eq(User::getId, SecurityUtils.getUser().getId())); + userService.setCurrentUserTenant(user.getTenantId()); return R.ok(); } diff --git a/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/UserService.java b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/UserService.java index 7384c524..b10980ca 100644 --- a/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/UserService.java +++ b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/UserService.java @@ -37,4 +37,11 @@ public interface UserService extends IService { */ User getUserAuthority(User user); + /** + * 设置当前用户多租户信息 + * @param tenantIds 多租户ids + * @return void + */ + void setCurrentUserTenant(String... tenantIds); + } diff --git a/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/impl/UserServiceImpl.java b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/impl/UserServiceImpl.java index 65d7e4b1..18c15673 100644 --- a/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/impl/UserServiceImpl.java +++ b/kicc-platform/kicc-platform-biz/kicc-system-biz/src/main/java/com/cloud/kicc/system/service/impl/UserServiceImpl.java @@ -8,6 +8,8 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.cloud.kicc.common.core.constant.SecurityConstants; import com.cloud.kicc.common.core.exception.CheckedException; import com.cloud.kicc.common.core.exception.CommonException; +import com.cloud.kicc.common.data.entity.KiccUser; +import com.cloud.kicc.common.security.util.SecurityUtils; import com.cloud.kicc.system.api.entity.Dept; import com.cloud.kicc.system.api.entity.Role; import com.cloud.kicc.system.api.entity.User; @@ -16,8 +18,15 @@ import com.cloud.kicc.system.mapper.UserMapper; import com.cloud.kicc.system.service.*; import lombok.AllArgsConstructor; import lombok.SneakyThrows; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -44,6 +53,7 @@ public class UserServiceImpl extends ServiceImpl implements Us private final RoleService roleService; private final MenuService menuService; private final TenantService tenantService; + private final TokenStore tokenStore; private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder(); @Override @@ -101,6 +111,38 @@ public class UserServiceImpl extends ServiceImpl implements Us return user; } + + @Override + public void setCurrentUserTenant(String... tenantIds) { + Authentication currentAuthentication = SecurityContextHolder.getContext().getAuthentication(); + if (currentAuthentication == null) { + new CommonException("当前用户未登录,请登录后重试!"); + } + OAuth2Authentication oAuth2Authentication = (OAuth2Authentication) currentAuthentication; + OAuth2AccessToken accessToken = tokenStore.getAccessToken(oAuth2Authentication); + OAuth2Request oAuth2Request = oAuth2Authentication.getOAuth2Request(); + KiccUser currentKiccUser = SecurityUtils.getUser(); + // 更新当前授权成功用户的信息 + KiccUser kiccUser = new KiccUser( + currentKiccUser.getId(), + currentKiccUser.getDeptId(), + currentKiccUser.getUsername(), + currentKiccUser.getPassword(), + currentKiccUser.getPhone(), + StrUtil.join(",", tenantIds), + currentKiccUser.isEnabled(), + currentKiccUser.isAccountNonExpired(), + currentKiccUser.isCredentialsNonExpired(), + currentKiccUser.isAccountNonLocked(), + currentKiccUser.getAuthorities() + ); + // 加载用户名密码身份验证令牌 + Authentication userAuthentication = new UsernamePasswordAuthenticationToken(kiccUser, "N/A", kiccUser.getAuthorities()); + OAuth2Authentication authentication = new OAuth2Authentication(oAuth2Request, userAuthentication); + authentication.setAuthenticated(true); + tokenStore.storeAccessToken(accessToken, authentication); + } + /** * 新增用户角色信息 * @param user 用户对象