|
|
@@ -0,0 +1,161 @@
|
|
|
+package org.jeecg.modules.zjrs.sso.service.impl;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import jakarta.annotation.Resource;
|
|
|
+import jakarta.servlet.http.HttpServletRequest;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.jeecg.common.api.vo.Result;
|
|
|
+import org.jeecg.common.constant.CommonConstant;
|
|
|
+import org.jeecg.common.system.util.JwtUtil;
|
|
|
+import org.jeecg.common.util.RedisUtil;
|
|
|
+import org.jeecg.common.util.oConvertUtils;
|
|
|
+import org.jeecg.config.JeecgBaseConfig;
|
|
|
+import org.jeecg.modules.zjrs.sso.entity.VRsUsers;
|
|
|
+import org.jeecg.modules.zjrs.sso.service.ILoginSSOService;
|
|
|
+import org.jeecg.modules.zjrs.sso.service.IVRsUsersService;
|
|
|
+import org.jeecg.modules.system.entity.SysDepart;
|
|
|
+import org.jeecg.modules.system.entity.SysUser;
|
|
|
+import org.jeecg.modules.system.service.ISysDepartService;
|
|
|
+import org.jeecg.modules.system.service.ISysDictService;
|
|
|
+import org.jeecg.modules.system.service.ISysUserService;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.util.LinkedHashMap;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+public class LoginSSOServiceImpl implements ILoginSSOService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ISysUserService sysUserService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ISysDepartService sysDepartService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ISysDictService sysDictService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IVRsUsersService vRsUsersService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private JeecgBaseConfig jeecgBaseConfig;
|
|
|
+
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private RedisUtil redisUtil;
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public JSONObject ssoLoginByToken(String usertoken, HttpServletRequest request) {
|
|
|
+ log.info("SSO单点登录开始,usertoken: {}", usertoken);
|
|
|
+
|
|
|
+ VRsUsers vRsUsers = vRsUsersService.getUserByLoginid(usertoken);
|
|
|
+ if (vRsUsers == null) {
|
|
|
+ log.warn("未找到用户信息,usertoken: {}", usertoken);
|
|
|
+ throw new RuntimeException("未找到用户信息");
|
|
|
+ }
|
|
|
+
|
|
|
+ String loginId = vRsUsers.getLoginid();
|
|
|
+ SysUser sysUser = sysUserService.getUserByName(loginId);
|
|
|
+
|
|
|
+ if (sysUser == null) {
|
|
|
+ log.info("SysUser表中未找到用户,开始自动同步用户信息,username: {}", loginId);
|
|
|
+ sysUser = vRsUsersService.syncUserToLocal(vRsUsers);
|
|
|
+ log.info("用户信息自动同步成功,username: {}", loginId);
|
|
|
+ }
|
|
|
+
|
|
|
+ Result<?> checkResult = sysUserService.checkUserIsEffective(sysUser);
|
|
|
+ if (!checkResult.isSuccess()) {
|
|
|
+ throw new RuntimeException(checkResult.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ return userInfo(sysUser, request, CommonConstant.CLIENT_TYPE_PC);
|
|
|
+ }
|
|
|
+
|
|
|
+ private JSONObject userInfo(SysUser sysUser, HttpServletRequest request, String clientType) {
|
|
|
+ String username = sysUser.getUsername();
|
|
|
+ String syspassword = sysUser.getPassword();
|
|
|
+ JSONObject obj = new JSONObject(new LinkedHashMap<>());
|
|
|
+
|
|
|
+ String token = JwtUtil.sign(username, syspassword, clientType);
|
|
|
+ redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
|
|
|
+ long expireTime = CommonConstant.CLIENT_TYPE_APP.equalsIgnoreCase(clientType)
|
|
|
+ ? JwtUtil.APP_EXPIRE_TIME * 2 / 1000
|
|
|
+ : JwtUtil.EXPIRE_TIME * 2 / 1000;
|
|
|
+ redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, expireTime);
|
|
|
+ obj.put("token", token);
|
|
|
+
|
|
|
+ handleSingleSignOn(username, token, clientType);
|
|
|
+
|
|
|
+ sysUserService.setLoginTenant(sysUser, obj, username, null);
|
|
|
+
|
|
|
+ obj.put("userInfo", sysUser);
|
|
|
+
|
|
|
+ List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
|
|
|
+ obj.put("departs", departs);
|
|
|
+ if (departs == null || departs.size() == 0) {
|
|
|
+ obj.put("multi_depart", 0);
|
|
|
+ sysUserService.updateUserDepart(username, null, null);
|
|
|
+ } else if (departs.size() == 1) {
|
|
|
+ sysUserService.updateUserDepart(username, departs.get(0).getOrgCode(), null);
|
|
|
+ obj.put("multi_depart", 1);
|
|
|
+ } else {
|
|
|
+ SysUser sysUserById = sysUserService.getById(sysUser.getId());
|
|
|
+ String loginOrgCode = sysUser.getLoginOrgCode();
|
|
|
+ boolean orgCodeInDeparts = departs.stream().anyMatch(d -> sysUserById.getOrgCode() != null && sysUserById.getOrgCode().equalsIgnoreCase(d.getOrgCode()));
|
|
|
+ if (!orgCodeInDeparts) {
|
|
|
+ sysUserById.setOrgCode(null);
|
|
|
+ }
|
|
|
+ if (oConvertUtils.isEmpty(sysUserById.getOrgCode())) {
|
|
|
+ String orgCode = oConvertUtils.isNotEmpty(loginOrgCode) ? loginOrgCode : departs.get(0).getOrgCode();
|
|
|
+ sysUserService.updateUserDepart(username, orgCode, null);
|
|
|
+ } else {
|
|
|
+ String orgCode = sysUserById.getOrgCode();
|
|
|
+ if (oConvertUtils.isNotEmpty(loginOrgCode) && !orgCode.equalsIgnoreCase(loginOrgCode)) {
|
|
|
+ sysUserService.updateUserDepart(username, loginOrgCode, null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ obj.put("multi_depart", 2);
|
|
|
+ }
|
|
|
+
|
|
|
+ String vue3Version = request.getHeader(CommonConstant.VERSION);
|
|
|
+ if (oConvertUtils.isEmpty(vue3Version)) {
|
|
|
+ obj.put("sysAllDictItems", sysDictService.queryAllDictItems());
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("SSO登录成功,username: {}", username);
|
|
|
+ return obj;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void handleSingleSignOn(String username, String newToken, String clientType) {
|
|
|
+ if (jeecgBaseConfig.getFirewall() == null || jeecgBaseConfig.getFirewall().getIsConcurrent() == null || Boolean.TRUE.equals(jeecgBaseConfig.getFirewall().getIsConcurrent())) {
|
|
|
+ log.debug("并发登录已启用:用户[{}]在{}端允许多地同时登录", username, clientType);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("【并发登录限制已开启】 用户[{}]在{}端不允许多地同时登录", username, clientType);
|
|
|
+ String redisKeyPrefix;
|
|
|
+ if (CommonConstant.CLIENT_TYPE_APP.equalsIgnoreCase(clientType)) {
|
|
|
+ redisKeyPrefix = CommonConstant.PREFIX_USER_TOKEN_APP;
|
|
|
+ } else if (CommonConstant.CLIENT_TYPE_PHONE.equalsIgnoreCase(clientType)) {
|
|
|
+ redisKeyPrefix = CommonConstant.PREFIX_USER_TOKEN_PHONE;
|
|
|
+ } else {
|
|
|
+ redisKeyPrefix = CommonConstant.PREFIX_USER_TOKEN_PC;
|
|
|
+ }
|
|
|
+
|
|
|
+ String userTokenKey = redisKeyPrefix + username;
|
|
|
+ Object oldTokenObj = redisUtil.get(userTokenKey);
|
|
|
+ if (oldTokenObj != null && !oldTokenObj.equals(newToken)) {
|
|
|
+ String oldToken = oldTokenObj.toString();
|
|
|
+ redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + oldToken);
|
|
|
+ redisUtil.set(CommonConstant.PREFIX_USER_TOKEN_ERROR_MSG + oldToken, "不允许同一账号多地同时登录,当前登录被踢掉!", 60 * 60);
|
|
|
+ log.info("【并发登录限制已开启】用户[{}]在{}端的旧登录已被踢下线!", username, clientType);
|
|
|
+ }
|
|
|
+
|
|
|
+ redisUtil.set(userTokenKey, newToken);
|
|
|
+ redisUtil.expire(userTokenKey, JwtUtil.EXPIRE_TIME * 2 / 1000);
|
|
|
+ }
|
|
|
+}
|