first commit

This commit is contained in:
陈现府
2025-11-20 10:45:16 +08:00
commit 8355431361
2643 changed files with 291314 additions and 0 deletions
@@ -0,0 +1,239 @@
package com.mhd.auth.app.application.service;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSONObject;
import com.mhd.common.core.constant.CacheConstants;
import com.mhd.common.core.constant.SecurityConstants;
import com.mhd.common.core.domain.po.UserConfigSwitchPo;
import com.mhd.common.core.exception.ServiceException;
import com.mhd.common.core.utils.JwtUtils;
import com.mhd.common.core.utils.RequestHeaderUtil;
import com.mhd.common.core.utils.ServletUtils;
import com.mhd.common.core.utils.StringUtils;
import com.mhd.common.core.utils.ip.IpUtil;
import com.mhd.common.core.utils.ip.IpUtils;
import com.mhd.common.core.utils.uuid.IdUtils;
import com.mhd.common.core.web.domain.AjaxResult;
import com.mhd.common.redis.service.RedisService;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.system.api.SystemServiceFeign;
import com.mhd.system.api.model.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* token验证处理
*
* @author mhd
*/
@Component
public class AppTokenService
{
@Resource
private RedisService redisService;
@Resource
private SystemServiceFeign systemServiceFeign;
protected static final long MILLIS_SECOND = 1000;
protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
private final static long expireTime = CacheConstants.EXPIRATION;
private final static String ACCESS_TOKEN = CacheConstants.LOGIN_TOKEN_KEY;
private final static Long MILLIS_MINUTE_TEN = CacheConstants.REFRESH_TIME * MILLIS_MINUTE;
/**
* 创建令牌
*/
public Map<String, Object> createToken(LoginUser loginUser)
{
String token = IdUtils.fastUUID();
Long userId = loginUser.getSysUser().getUserId();
String userName = loginUser.getSysUser().getUserName();
loginUser.setToken(token);
loginUser.setUserid(userId);
loginUser.setUsername(userName);
loginUser.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
refreshToken(loginUser);
// Jwt存储信息
Map<String, Object> claimsMap = new HashMap<String, Object>();
claimsMap.put(SecurityConstants.USER_KEY, token);
claimsMap.put(SecurityConstants.DETAILS_USER_ID, userId);
claimsMap.put(SecurityConstants.DETAILS_USERNAME, userName);
// 接口返回信息
Map<String, Object> rspMap = new HashMap<String, Object>();
rspMap.put("access_token", JwtUtils.createToken(claimsMap));
rspMap.put("expires_in", expireTime);
return rspMap;
}
/**
* 获取用户身份信息
*
* @return 用户信息
*/
public LoginUser getLoginUser()
{
return getLoginUser(ServletUtils.getRequest());
}
/**
* 获取用户身份信息
*
* @return 用户信息
*/
public LoginUser getLoginUser(HttpServletRequest request)
{
// 获取请求携带的令牌
String token = SecurityUtils.getToken(request);
return getLoginUser(token);
}
/**
* 获取用户身份信息
*
* @return 用户信息
*/
public LoginUser getLoginUser(String token)
{
LoginUser user = null;
try
{
if (StringUtils.isNotEmpty(token))
{
String userkey = JwtUtils.getUserKey(token);
user = redisService.getCacheObject(getTokenKey(userkey));
return user;
}
}
catch (Exception e)
{
}
return user;
}
/**
* 设置用户身份信息
*/
public void setLoginUser(LoginUser loginUser)
{
if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken()))
{
refreshToken(loginUser);
}
}
/**
* 删除用户缓存信息
*/
public void delLoginUser(String token)
{
if (StringUtils.isNotEmpty(token))
{
String userkey = JwtUtils.getUserKey(token);
redisService.deleteObject(getTokenKey(userkey));
}
}
/**
* 验证令牌有效期,相差不足120分钟,自动刷新缓存
*
* @param loginUser
*/
public void verifyToken(LoginUser loginUser)
{
long expireTime = loginUser.getExpireTime();
long currentTime = System.currentTimeMillis();
if (expireTime - currentTime <= MILLIS_MINUTE_TEN)
{
refreshToken(loginUser);
}
}
/**
* 刷新令牌有效期
* 过期时间720分钟
* @param loginUser 登录信息
*/
public void refreshToken(LoginUser loginUser)
{
loginUser.setLoginTime(System.currentTimeMillis());
loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
// 根据uuid将loginUser缓存
String userKey = getTokenKey(loginUser.getToken());
redisService.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
}
private String getTokenKey(String token)
{
return ACCESS_TOKEN + token;
}
/**
* @Description 创建令牌方法新
* @Author Alex
* @Date 2022/12/6 23:09
*/
public Map<String, Object> createTokenApi(LoginUser loginUser)
{
String token = IdUtils.fastUUID();
Long userId = loginUser.getUserPo().getUserId();
String userAccount = loginUser.getUserPo().getUserAccount();
Long topOrganizationId = loginUser.getUserPo().getTopOrganizationId();
loginUser.setToken(token);
loginUser.setUserid(userId);
loginUser.setUsername(userAccount);
loginUser.setOs("2");
loginUser.setTerminal(RequestHeaderUtil.getTerminal());
loginUser.setTerminalLogo(RequestHeaderUtil.getTerminalOS());
loginUser.setInitialLoginTime(System.currentTimeMillis());
loginUser.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
loginUser.setIpRegion(StrUtil.isNotEmpty(loginUser.getIpaddr()) ? IpUtil.getLocationSplicing(loginUser.getIpaddr()) : "");
refreshToken(loginUser);
//是否单点登录
AjaxResult<?> ajaxResult = systemServiceFeign.getUserConfigSwitchInfoByOrgId(topOrganizationId);
if (!"200".equals(String.valueOf(ajaxResult.get("code"))) || ObjUtil.isNull(JSONObject.toJSONString(ajaxResult.get("data")))) {
throw new ServiceException("获取开关配置信息失败");
}
UserConfigSwitchPo userConfigSwitchPo = JSONUtil.toBean(JSONUtil.toJsonStr(ajaxResult.get("data")), UserConfigSwitchPo.class);
Integer isSingleSign = userConfigSwitchPo.getIsSingleSign();//单点登录:0-否,1-是
if (ObjUtil.isNotNull(isSingleSign) && isSingleSign == 1) {
String key = CacheConstants.USER_LOGIN_TOKENS + userId;
String tokenStr = redisService.getCacheObject(key);
if (StrUtil.isNotEmpty(tokenStr)) {
redisService.deleteObject(tokenStr);
}
redisService.setCacheObject(key, CacheConstants.LOGIN_TOKEN_KEY + token, expireTime, TimeUnit.MINUTES);
}
// Jwt存储信息
Map<String, Object> claimsMap = new HashMap<String, Object>();
claimsMap.put(SecurityConstants.USER_KEY, token);
claimsMap.put(SecurityConstants.DETAILS_USER_ID, userId);
claimsMap.put(SecurityConstants.DETAILS_USERNAME, userAccount);
claimsMap.put(SecurityConstants.TOP_ORGANIZATION_ID, topOrganizationId);
// 接口返回信息
Map<String, Object> rspMap = new HashMap<String, Object>();
rspMap.put("access_token", JwtUtils.createToken(claimsMap));
rspMap.put("app_token", "Bearer "+JwtUtils.createToken(claimsMap));
rspMap.put("expires_in", expireTime);
rspMap.put("user_id", userId);
return rspMap;
}
}
@@ -0,0 +1,572 @@
package com.mhd.auth.app.application.service;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.base.Strings;
import com.mhd.auth.app.interfaces.dto.LoginDTO;
import com.mhd.auth.app.infrastructure.feign.OrganizationServiceFeign;
import com.mhd.auth.app.infrastructure.feign.UserServiceFeign;
import com.mhd.auth.system.service.SysLoginService;
import com.mhd.auth.system.service.SysPasswordService;
import com.mhd.common.core.constant.*;
import com.mhd.common.core.domain.dto.AppConfigDTO;
import com.mhd.common.core.domain.entity.R;
import com.mhd.common.core.domain.po.*;
import com.mhd.common.core.enums.UserStatus;
import com.mhd.common.core.exception.ServiceException;
import com.mhd.common.core.exception.digitalLogisticsException.DigitalLogisticsException;
import com.mhd.common.core.exception.digitalLogisticsException.UserError;
import com.mhd.common.core.utils.*;
import com.mhd.common.core.utils.ip.IpUtil;
import com.mhd.common.core.utils.ip.IpUtils;
import com.mhd.common.core.web.domain.AjaxResult;
import com.mhd.common.log.service.AsyncLogService;
import com.mhd.common.redis.service.RedisService;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.common.security.utils.password.PasswordUtil;
import com.mhd.system.api.AssociationWarehouseFeign;
import com.mhd.system.api.SystemServiceFeign;
import com.mhd.system.api.domain.SysLogininforPo;
import com.mhd.system.api.domain.SysUser;
import com.mhd.system.api.domain.UserDTO;
import com.mhd.system.api.model.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
/**
* 登录校验方法
*
* @author mhd
*/
@Slf4j
@Component
public class TokenLoginApplicationService {
@Resource
private UserServiceFeign userServiceFeign;
@Resource
private OrganizationServiceFeign organizationServiceFeign;
@Resource
private RedisService redisService;
@Resource
private SysLoginService sysLoginService;
@Autowired
private AsyncLogService asyncLogService;
@Resource
private SysPasswordService sysPasswordService;
@Autowired
private SystemServiceFeign systemServiceFeign;
/**
* @Description 验证码登录
* @Author Alex
* @Date 2022/12/9 15:44
*/
public LoginUser loginByVerificationCode(LoginDTO loginDTO) {
//手机号
String userPhone = loginDTO.getUserPhone();
//验证码
String verificationCode = loginDTO.getVerificationCode();
//请求域名
String path = loginDTO.getPath();
// 用户名或密码为空 错误
if (StringUtils.isAnyBlank(userPhone, verificationCode)) {
recordLogininfor(userPhone, Constants.LOGIN_FAIL, "请输入手机号和短信验证码", 1);
throw new ServiceException("请输入手机号和短信验证码");
}
//调用工具类校验,校验手机号格式错误
if (!RegexUtil.isPhoneLegal(userPhone)) {
recordLogininfor(userPhone, Constants.LOGIN_FAIL, UserError.USER_PHONE_REG_ERROR.errmsg(), 1);
throw new DigitalLogisticsException(UserError.USER_PHONE_REG_ERROR);
}
//根据域名获取一级组织ID
// R<Long> topOrganizationIdR = userServiceFeign.getOrganizationByPath(path, SecurityConstants.INNER);
AjaxResult topOrganizationIdR = organizationServiceFeign.getOrganizationByPath(path);
if (ObjectUtil.isNull(topOrganizationIdR) || ObjectUtil.isNull(topOrganizationIdR.get("data"))) {
recordLogininfor(userPhone, Constants.LOGIN_FAIL, "登录用户组织不存在", 1);
throw new ServiceException("登录用户:" + userPhone + " 组织不存在");
}
//租户一级组织ID
SysTenantsPo sysTenantsPo = JSON.parseObject(JSON.toJSONString(topOrganizationIdR.get("data")), SysTenantsPo.class);
Long topOrganizationId = sysTenantsPo.getOrganizationId();
//获取用户信息,组装dto
UserDTO userDTO = new UserDTO();
userDTO.setUserPhone(userPhone);
userDTO.setTopOrganizationId(topOrganizationId);
userDTO.setOrganizationId(topOrganizationId);
// 查询用户信息,查询组织下用户是否存在
R<LoginUser> userResult = userServiceFeign.getUserByTopOrganizationUserPhone(userDTO, SecurityConstants.INNER);
if (R.FAIL == userResult.getCode()) {
throw new ServiceException(userResult.getMsg());
}
LoginUser userInfo = userResult.getData();
//获取用户角色信息,分析用户状态是否正常
UserPo userPo = userResult.getData().getUserPo();
if (StringUtils.isNull(userResult.getData()) || StringUtils.isNull(userResult.getData().getUserPo())) {
//验证码登录校验验证码
String key = CacheConstants.SMS_LOGIN + userPhone;
Object object = redisService.getCacheObject(key) == null ? "":redisService.getCacheObject(key);
if(!ObjectUtil.equal(String.valueOf(object),verificationCode) && !ObjectUtil.equal(verificationCode, SmsConstants.universalCode)){
recordLogininfor(userPhone, Constants.LOGIN_FAIL, "验证码错误", 1);
throw new ServiceException("验证码错误");
}
//获取包名对应的业务(存在需要查询业务,不存在保存为无业务模式)
if (StringUtils.isNotBlank(loginDTO.getAppMark())){
AppConfigDTO appConfigDTO = new AppConfigDTO();
appConfigDTO.setAppPackage(loginDTO.getAppMark());
appConfigDTO.setTopOrganizationId(topOrganizationId);
R<AppConfigPO> apppackageResult = organizationServiceFeign.getAppConfigByAppPackageFeign(appConfigDTO);
if (ObjectUtil.isNotNull(apppackageResult) && ObjectUtil.isNotNull(apppackageResult.getData())) {
AppConfigPO data = apppackageResult.getData();
String appRangeCode = data.getAppRangeCode();
if (StringUtils.isNotBlank(appRangeCode)){
if (appRangeCode.contains("shipping_business") && appRangeCode.contains("carrier_business")){
userDTO.setBusinessType(5);
}else if (appRangeCode.contains("shipping_business")){
userDTO.setBusinessType(1);
}else if (appRangeCode.contains("carrier_business")){
userDTO.setBusinessType(2);
}
}
}
}else {
userDTO.setBusinessType(4);
}
userDTO.setOrganizationName(sysTenantsPo.getOrganizationName());
userResult = userServiceFeign.registerAddUser(userDTO, SecurityConstants.INNER);
userInfo = userResult.getData();
} else {
//用户状态:0-无状态,1-正常,2-锁定
if (UserStatus.DELETED.getCode().equals(String.valueOf(userPo.getUserStatus()))) {
recordLogininfor(userPo, Constants.LOGIN_FAIL, "用户已停用,请联系管理员", 1);
throw new ServiceException("对不起,您的账号:" + userPhone + " 已停用");
}
//校验验证码是否正确
sysPasswordService.validate(userPo, verificationCode, 1, null);
}
return userInfo;
}
public void logout(UserPo userPo) {
recordLogininfor(userPo, Constants.LOGOUT, "退出成功", 3);
}
/**
* 注册
*/
public void register(String username, String password) {
// 用户名或密码为空 错误
if (StringUtils.isAnyBlank(username, password)) {
throw new ServiceException("用户/密码必须填写");
}
if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|| username.length() > UserConstants.USERNAME_MAX_LENGTH) {
throw new ServiceException("账户长度必须在2到20个字符之间");
}
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
throw new ServiceException("密码长度必须在5到20个字符之间");
}
// 注册用户信息
SysUser sysUser = new SysUser();
sysUser.setUserName(username);
sysUser.setNickName(username);
sysUser.setPassword(SecurityUtils.encryptPassword(password));
//TODO app注册没写
/*R<?> registerResult = userServiceFeign.registerUserInfo(sysUser, SecurityConstants.INNER);
if (R.FAIL == registerResult.getCode()) {
throw new ServiceException(registerResult.getMsg());
}*/
// recordLogininfor(username, Constants.REGISTER, "注册成功");
}
/**
* 记录登录信息
*
* @param username 用户名
* @param status 状态
* @param message 消息内容
* @return
*/
public void recordLogininfor(String username, String status, String message, Integer behaviorType) {
SysLogininforPo logininfor = new SysLogininforPo();
logininfor.setUserAccount(username);
logininfor.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
logininfor.setLocation(StrUtil.isNotEmpty(logininfor.getIpaddr()) ? IpUtil.getLocationSplicing(logininfor.getIpaddr()) : "");
logininfor.setTerminal(RequestHeaderUtil.getTerminal());
logininfor.setTerminalLogo(RequestHeaderUtil.getTerminalOS());
logininfor.setBehaviorType(behaviorType);
logininfor.setMsg(message);
logininfor.setAccessTime(DateUtil.date());
// 日志状态
if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) {
logininfor.setStatus(Constants.LOGIN_SUCCESS_STATUS);
} else if (Constants.LOGIN_FAIL.equals(status)) {
logininfor.setStatus(Constants.LOGIN_FAIL_STATUS);
}
asyncLogService.saveLogininfor(logininfor);
}
/**
* 记录登录信息
*/
public void recordLogininfor(UserPo userPo, String status, String message, Integer behaviorType) {
SysLogininforPo logininfor = new SysLogininforPo();
logininfor.setUserAccount(userPo.getUserAccount());
logininfor.setUserName(userPo.getUserName());
logininfor.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
logininfor.setLocation(StrUtil.isNotEmpty(logininfor.getIpaddr()) ? IpUtil.getLocationSplicing(logininfor.getIpaddr()) : "");
logininfor.setTerminal(RequestHeaderUtil.getTerminal());
logininfor.setTerminalLogo(RequestHeaderUtil.getTerminalOS());
logininfor.setBehaviorType(behaviorType);
logininfor.setMsg(message);
logininfor.setOrganizationId(userPo.getOrganizationId());
logininfor.setOrganizationName(userPo.getOrganizationName());
logininfor.setTopOrganizationId(userPo.getTopOrganizationId());
logininfor.setAccessTime(DateUtil.date());
// 日志状态
if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) {
logininfor.setStatus(Constants.LOGIN_SUCCESS_STATUS);
} else if (Constants.LOGIN_FAIL.equals(status)) {
logininfor.setStatus(Constants.LOGIN_FAIL_STATUS);
}
asyncLogService.saveLogininfor(logininfor);
}
public SysLogininforPo recordLogininfoTwo(UserPo userPo, String status, String message, Integer behaviorType,long beginTime) {
SysLogininforPo logininfor = new SysLogininforPo();
logininfor.setUserAccount(userPo.getUserAccount());
logininfor.setUserName(userPo.getUserName());
logininfor.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
logininfor.setLocation(StrUtil.isNotEmpty(logininfor.getIpaddr()) ? IpUtil.getLocationSplicing(logininfor.getIpaddr()) : "");
logininfor.setTerminal(RequestHeaderUtil.getTerminal());
logininfor.setTerminalLogo(RequestHeaderUtil.getTerminalOS());
logininfor.setBehaviorType(behaviorType);
logininfor.setMsg(message);
logininfor.setOrganizationId(userPo.getOrganizationId());
logininfor.setOrganizationName(userPo.getOrganizationName());
logininfor.setTopOrganizationId(userPo.getTopOrganizationId());
logininfor.setAccessTime(DateUtil.date());
// 日志状态
if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) {
logininfor.setStatus(Constants.LOGIN_SUCCESS_STATUS);
} else if (Constants.LOGIN_FAIL.equals(status)) {
logininfor.setStatus(Constants.LOGIN_FAIL_STATUS);
}
long time = System.currentTimeMillis() - beginTime;
logininfor.setResponseTime(String.valueOf(time));
asyncLogService.saveLogininfor(logininfor);
return logininfor;
}
/**
* @Description 新登录接口
* @Author Alex
* @Date 2022/12/6 23:06
*/
public LoginUser loginApi(LoginDTO loginDTO) {
long beginTime = System.currentTimeMillis();
String username = loginDTO.getUsername();
//用户密码传值
String password = loginDTO.getPassword();
//手机号
String userPhone = loginDTO.getUserPhone();
//登录方式 1-账号密码登录 2-验证码登录
String loginType = "1";
String userNameOrUserPhone = "";
LoginUser userInfo = new LoginUser();
//如果手机号传值了,则进入验证码登录方法,否则继续账号密码登录
if (!Strings.isNullOrEmpty(userPhone)) {
loginType = "2";
userNameOrUserPhone = userPhone;
userInfo = loginByVerificationCode(loginDTO);
}
else {
userNameOrUserPhone = username;
//请求域名
String path = loginDTO.getPath();
// 用户名或密码为空 错误
if (StringUtils.isAnyBlank(username, password)) {
recordLogininfor(username, Constants.LOGIN_FAIL, "用户/密码必须填写", 1);
throw new ServiceException("用户/密码必须填写");
}
//解密登录密码
String userPassword = AESUtil.decrypt(password);
if (!RegexUtil.isPasswordLegal(userPassword)) {
recordLogininfor(username, Constants.LOGIN_FAIL, UserError.USER_PASSWORD_REG_ERROR.errmsg(), 1);
throw new DigitalLogisticsException(UserError.USER_PASSWORD_REG_ERROR);
}
//调用工具类校验,用户账号格式错误
if (!RegexUtil.isAccountLegal(username)) {
recordLogininfor(username, Constants.LOGIN_FAIL, UserError.USER_ACCOUNT_REG_ERROR.errmsg(), 1);
throw new DigitalLogisticsException(UserError.USER_ACCOUNT_REG_ERROR);
}
//根据域名获取一级组织ID
R<Long> topOrganizationIdR = userServiceFeign.getOrganizationByPath(path, SecurityConstants.INNER);
if (topOrganizationIdR == null) {
recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户组织不存在", 1);
throw new ServiceException("登录用户:" + username + " 组织不存在");
}
//租户一级组织ID
Long topOrganizationId = topOrganizationIdR.getData();
//获取用户信息,组装dto
UserDTO userDTO = new UserDTO();
userDTO.setUserAccount(username);
userDTO.setTopOrganizationId(topOrganizationId);
// userDTO.setOrganizationId(topOrganizationId);
// 查询用户信息,查询组织下用户是否存在
R<LoginUser> userResult = userServiceFeign.getUserByTopOrganizationUserAccount(userDTO, SecurityConstants.INNER);
if (R.FAIL == userResult.getCode()) {
throw new ServiceException(userResult.getMsg());
}
if (StringUtils.isNull(userResult.getData())) {
recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在", 1);
throw new ServiceException("登录用户:" + username + " 不存在");
}
userInfo = userResult.getData();
//获取用户角色信息,分析用户状态是否正常
UserPo userPo = userResult.getData().getUserPo();
//判断设否设置登录密码
if (StrUtil.isEmpty(userPo.getUserPassword())) {
recordLogininfor(userPo, Constants.LOGIN_FAIL, "对不起,您的账号未设置登录密码,请先通过验证码进行登录,进行密码设置", 1);
throw new ServiceException("对不起,您的账号:" + username + " 未设置登录密码,请先通过验证码进行登录,进行密码设置");
}
//删除标记:0-无状态,1-正常,2-已删除
if (UserStatus.DELETED.getCode().equals(String.valueOf(userPo.getDelFlag()))) {
recordLogininfor(userPo, Constants.LOGIN_FAIL, "对不起,您的账号已被删除", 1);
throw new ServiceException("对不起,您的账号:" + username + " 已被删除");
}
//用户状态:0-无状态,1-正常,2-锁定
if (UserStatus.DELETED.getCode().equals(String.valueOf(userPo.getUserStatus()))) {
recordLogininfor(userPo, Constants.LOGIN_FAIL, "用户已停用,请联系管理员", 1);
throw new ServiceException("对不起,您的账号:" + username + " 已停用");
}
//校验用户账号密码是否正确
sysPasswordService.validate(userPo, userPassword, 0, null);
//校验用户账号密码是否正确
if (!PasswordUtil.matchesPassword(userPo.getUserAccount(), userPassword, userPo.getUserSalt(), userPo.getUserPassword())) {
recordLogininfor(userPo, Constants.LOGIN_FAIL, "用户密码错误", 1);
throw new ServiceException("用户不存在/密码错误");
}
}
R<OrganizationPo> organizationInfo = organizationServiceFeign.getInfoForIdList(userInfo.getUserPo().getOrganizationId());
if (ObjectUtil.isNull(organizationInfo) || ObjectUtil.isNull(organizationInfo.getData())) {
throw new ServiceException("登录用户组织不存在");
}
OrganizationPo data = organizationInfo.getData();
userInfo.setOrganizationPo(data);
sysLoginService.processWLHYInformation(loginType, "2", userNameOrUserPhone, userInfo);
//查询用户角色
AjaxResult roleListAjaxResult = userServiceFeign.getRoleListByUserId(userInfo.getUserPo().getUserId());
if ("200".equals(String.valueOf(roleListAjaxResult.get("code"))) && ObjectUtil.isNotNull(roleListAjaxResult.get("data"))) {
List<RolePO> rolePOS = JSONUtil.toList(JSONUtil.toJsonStr(roleListAjaxResult.get("data")), RolePO.class);
if (rolePOS != null && rolePOS.size() > 0){
userInfo.setRoleList(rolePOS.stream().map(RolePO::getRoleName).collect(Collectors.toList()));
userInfo.setRoleIdList(rolePOS.stream().map(RolePO::getRoleId).collect(Collectors.toList()));
}
}
recordLogininfoTwo(userInfo.getUserPo(), Constants.LOGIN_SUCCESS, "登录成功", 1,beginTime);
return userInfo;
}
/**
* @Description wms 新登录接口
* @Author Alex
* @Date 2022/12/6 23:06
*/
public LoginUser loginApiByWms(LoginDTO loginDTO) {
String username = loginDTO.getUsername();
//用户密码传值
String password = loginDTO.getPassword();
//手机号
String userPhone = loginDTO.getUserPhone();
//登录方式 1-账号密码登录 2-验证码登录
LoginUser userInfo = new LoginUser();
//如果手机号传值了,则进入验证码登录方法,否则继续账号密码登录
if (!Strings.isNullOrEmpty(userPhone)) {
userInfo = loginByVerificationCodeByWms(loginDTO);
} else {
//请求域名
String path = loginDTO.getPath();
// 用户名或密码为空 错误
if (StringUtils.isAnyBlank(username, password)) {
recordLogininfor(username, Constants.LOGIN_FAIL, "用户/密码必须填写", 1);
throw new ServiceException("用户/密码必须填写");
}
//解密登录密码
String userPassword = AESUtil.decrypt(password);
if (!RegexUtil.isPasswordLegal(userPassword)) {
recordLogininfor(username, Constants.LOGIN_FAIL, UserError.USER_PASSWORD_REG_ERROR.errmsg(), 1);
throw new DigitalLogisticsException(UserError.USER_PASSWORD_REG_ERROR);
}
//调用工具类校验,用户账号格式错误
if (!RegexUtil.isAccountLegal(username)) {
recordLogininfor(username, Constants.LOGIN_FAIL, UserError.USER_ACCOUNT_REG_ERROR.errmsg(), 1);
throw new DigitalLogisticsException(UserError.USER_ACCOUNT_REG_ERROR);
}
//根据域名获取一级组织ID
R<Long> topOrganizationIdR = userServiceFeign.getOrganizationByPath(path, SecurityConstants.INNER);
if (topOrganizationIdR == null) {
recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户组织不存在", 1);
throw new ServiceException("登录用户:" + username + " 组织不存在");
}
//租户一级组织ID
Long topOrganizationId = topOrganizationIdR.getData();
//获取用户信息,组装dto
UserDTO userDTO = new UserDTO();
userDTO.setUserAccount(username);
userDTO.setTopOrganizationId(topOrganizationId);
// 查询用户信息,查询组织下用户是否存在
R<LoginUser> userResult = userServiceFeign.getUserByTopOrganizationUserAccount(userDTO, SecurityConstants.INNER);
if (R.FAIL == userResult.getCode()) {
throw new ServiceException(userResult.getMsg());
}
if (StringUtils.isNull(userResult.getData())) {
recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在", 1);
throw new ServiceException("登录用户:" + username + " 不存在");
}
userInfo = userResult.getData();
//获取用户角色信息,分析用户状态是否正常
UserPo userPo = userResult.getData().getUserPo();
//判断设否设置登录密码
if (StrUtil.isEmpty(userPo.getUserPassword())) {
recordLogininfor(userPo, Constants.LOGIN_FAIL, "对不起,您的账号未设置登录密码,请先通过验证码进行登录,进行密码设置", 1);
throw new ServiceException("对不起,您的账号:" + username + " 未设置登录密码,请先通过验证码进行登录,进行密码设置");
}
//删除标记:0-无状态,1-正常,2-已删除
if (UserStatus.DELETED.getCode().equals(String.valueOf(userPo.getDelFlag()))) {
recordLogininfor(userPo, Constants.LOGIN_FAIL, "对不起,您的账号已被删除", 1);
throw new ServiceException("对不起,您的账号:" + username + " 已被删除");
}
//用户状态:0-无状态,1-正常,2-锁定
if (UserStatus.DELETED.getCode().equals(String.valueOf(userPo.getUserStatus()))) {
recordLogininfor(userPo, Constants.LOGIN_FAIL, "用户已停用,请联系管理员", 1);
throw new ServiceException("对不起,您的账号:" + username + " 已停用");
}
//校验用户账号密码是否正确
sysPasswordService.validateByWms(userPo, userPassword, 0);
//校验用户账号密码是否正确
if (!PasswordUtil.matchesPassword(userPo.getUserAccount(), userPassword, userPo.getUserSalt(), userPo.getUserPassword())) {
recordLogininfor(userPo, Constants.LOGIN_FAIL, "用户密码错误", 1);
throw new ServiceException("用户不存在/密码错误");
}
}
R<OrganizationPo> organizationInfo = organizationServiceFeign.getInfoForIdList(userInfo.getUserPo().getOrganizationId());
if (ObjectUtil.isNull(organizationInfo) || ObjectUtil.isNull(organizationInfo.getData())) {
throw new ServiceException("登录用户组织不存在");
}
OrganizationPo data = organizationInfo.getData();
userInfo.setOrganizationPo(data);
recordLogininfor(userInfo.getUserPo(), Constants.LOGIN_SUCCESS, "登录成功", 1);
//查询用户角色
AjaxResult roleListAjaxResult = userServiceFeign.getRoleListByUserId(userInfo.getUserPo().getUserId());
if ("200".equals(String.valueOf(roleListAjaxResult.get("code"))) && ObjectUtil.isNotNull(roleListAjaxResult.get("data"))) {
List<RolePO> rolePOS = JSONUtil.toList(JSONUtil.toJsonStr(roleListAjaxResult.get("data")), RolePO.class);
if (rolePOS != null && rolePOS.size() > 0){
userInfo.setRoleList(rolePOS.stream().map(RolePO::getRoleName).collect(Collectors.toList()));
userInfo.setRoleIdList(rolePOS.stream().map(RolePO::getRoleId).collect(Collectors.toList()));
}
}
//判断是否选择了仓库 选择了仓库将登录信息赋值进去
AssociationWarehouseFeign associationWarehouseFeign = new AssociationWarehouseFeign();
associationWarehouseFeign.setCorrelationId(userInfo.getUserPo().getUserId());
systemServiceFeign.setWarehouseInfo(associationWarehouseFeign);
return userInfo;
}
/**
* @Description wms 验证码登录
* @Author Alex
* @Date 2022/12/9 15:44
*/
public LoginUser loginByVerificationCodeByWms(LoginDTO loginDTO) {
//手机号
String userPhone = loginDTO.getUserPhone();
//验证码
String verificationCode = loginDTO.getVerificationCode();
//请求域名
String path = loginDTO.getPath();
// 用户名或密码为空 错误
if (StringUtils.isAnyBlank(userPhone, verificationCode)) {
recordLogininfor(userPhone, Constants.LOGIN_FAIL, "请输入手机号和短信验证码", 1);
throw new ServiceException("请输入手机号和短信验证码");
}
//调用工具类校验,校验手机号格式错误
if (!RegexUtil.isPhoneLegal(userPhone)) {
recordLogininfor(userPhone, Constants.LOGIN_FAIL, UserError.USER_PHONE_REG_ERROR.errmsg(), 1);
throw new DigitalLogisticsException(UserError.USER_PHONE_REG_ERROR);
}
//根据域名获取一级组织ID
AjaxResult topOrganizationIdR = organizationServiceFeign.getOrganizationByPath(path);
if (ObjectUtil.isNull(topOrganizationIdR) || ObjectUtil.isNull(topOrganizationIdR.get("data"))) {
recordLogininfor(userPhone, Constants.LOGIN_FAIL, "登录用户组织不存在", 1);
throw new ServiceException("登录用户:" + userPhone + " 组织不存在");
}
//租户一级组织ID
SysTenantsPo sysTenantsPo = JSON.parseObject(JSON.toJSONString(topOrganizationIdR.get("data")), SysTenantsPo.class);
Long topOrganizationId = sysTenantsPo.getOrganizationId();
//获取用户信息,组装dto
UserDTO userDTO = new UserDTO();
userDTO.setUserPhone(userPhone);
userDTO.setTopOrganizationId(topOrganizationId);
userDTO.setOrganizationId(topOrganizationId);
// 查询用户信息,查询组织下用户是否存在
R<LoginUser> userResult = userServiceFeign.getUserByTopOrganizationUserPhone(userDTO, SecurityConstants.INNER);
if (R.FAIL == userResult.getCode()) {
throw new ServiceException(userResult.getMsg());
}
LoginUser userInfo = userResult.getData();
//获取用户角色信息,分析用户状态是否正常
UserPo userPo = userResult.getData().getUserPo();
//用户状态:0-无状态,1-正常,2-锁定
if (UserStatus.DELETED.getCode().equals(String.valueOf(userPo.getUserStatus()))) {
recordLogininfor(userPo, Constants.LOGIN_FAIL, "用户已停用,请联系管理员", 1);
throw new ServiceException("对不起,您的账号:" + userPhone + " 已停用");
}
//校验验证码是否正确
sysPasswordService.validateByWms(userPo, verificationCode, 1);
return userInfo;
}
}
@@ -0,0 +1,27 @@
package com.mhd.auth.app.infrastructure.feign;
import com.mhd.common.core.constant.SecurityConstants;
import com.mhd.common.core.constant.ServiceNameConstants;
import com.mhd.common.core.domain.entity.R;
import com.mhd.system.api.domain.SysLogininforPo;
import com.mhd.system.api.domain.SysOperLogPo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
/**
* @Description 调用产品中台-组织模块
* @Author Alex
* @Date 2022/12/2 13:38
*/
@FeignClient(ServiceNameConstants.SYSTEM_SERVICE)
public interface LogServiceFeign {
@PostMapping("/operlog")
public R<Boolean> saveLog(@RequestBody SysOperLogPo sysOperLogPo, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
@PostMapping("/logininfor")
public R<Boolean> saveLogininfor(@RequestBody SysLogininforPo sysLogininforPo, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
}
@@ -0,0 +1,51 @@
package com.mhd.auth.app.infrastructure.feign;
import com.mhd.common.core.constant.ServiceNameConstants;
import com.mhd.common.core.domain.dto.AppConfigDTO;
import com.mhd.common.core.domain.entity.R;
import com.mhd.common.core.domain.po.AppConfigPO;
import com.mhd.common.core.domain.po.OrganizationPo;
import com.mhd.common.core.web.domain.AjaxResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
/**
* @Description 调用产品中台-组织模块
* @Author Alex
* @Date 2022/12/2 13:38
*/
@FeignClient(ServiceNameConstants.PRODUCT_CENTER)
public interface OrganizationServiceFeign {
/**
* @Description 获取一级组织
* @Author Alex
* @Date 2022/12/2 13:37
*/
@GetMapping("/organization/selectTopId/{id}")
public AjaxResult getTopOrganization(@PathVariable("id") Long id);
@GetMapping("/organization/selectTopIdByTenantsDomainName/{tenantsDomainName}")
public AjaxResult getOrganizationByPath(@PathVariable("tenantsDomainName") String tenantsDomainName);
/**
* @Description 根据id查询组织信息(包含所有的子组织id)
* @Author Alex
* @Date 2022/12/6 22:11
*/
@GetMapping("/organization/getInfoForIdList/{id}")
R<OrganizationPo> getInfoForIdList(@PathVariable("id") Long id);
/**
* @Description 根据id查询组织信息(包含所有的子组织id)
* @Author Alex
* @Date 2022/12/6 22:11
*/
@PostMapping("/appConfigApi/getAppConfigByAppPackageFeign")
R<AppConfigPO> getAppConfigByAppPackageFeign(@RequestBody AppConfigDTO appConfigDTO);
}
@@ -0,0 +1,54 @@
package com.mhd.auth.app.infrastructure.feign;
import com.mhd.common.core.constant.SecurityConstants;
import com.mhd.common.core.constant.ServiceNameConstants;
import com.mhd.common.core.domain.entity.R;
import com.mhd.common.core.web.domain.AjaxResult;
import com.mhd.system.api.domain.UserDTO;
import com.mhd.system.api.model.LoginUser;
import io.swagger.annotations.ApiOperation;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
/**
* @Description 调用产品中台-组织模块
* @Author Alex
* @Date 2022/12/2 13:38
*/
@FeignClient(ServiceNameConstants.USER_CENTER)
public interface UserServiceFeign {
@GetMapping("/user/info/{username}")
public R<LoginUser> getUserInfo(@PathVariable("username") String username, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* @Description 根据域名获取组织ID
* @Author Alex
* @Date 2022/12/6 22:11
*/
@GetMapping("/userApi/getOrganizationByPath/{path}")
public R<Long> getOrganizationByPath(@PathVariable("path") String path, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 通过用户名查询用户信息
*
* @return 结果
*/
@PostMapping("/userApi/getUserByTopOrganizationUserAccount")
public R<LoginUser> getUserByTopOrganizationUserAccount(@RequestBody UserDTO userDTO, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
@PostMapping("/userApi/getUserByTopOrganizationUserPhone")
public R<LoginUser> getUserByTopOrganizationUserPhone(@RequestBody UserDTO userDTO, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
@PostMapping("/userApi/add")
public R<LoginUser> addUser(@RequestBody UserDTO userDTO, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
@PostMapping("/userApi/registerAddUser")
R<LoginUser> registerAddUser(@RequestBody UserDTO userDTO, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
@ApiOperation("根据用户ID查询角色列表")
@GetMapping("/roleApi/getRoleListByUserId/{userId}")
public AjaxResult getRoleListByUserId(@PathVariable("userId") Long userId);
}
@@ -0,0 +1,37 @@
package com.mhd.auth.app.interfaces.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @Description
* @Author Alex
* @Date 2022/12/6 22:15
*/
@Data
public class LoginDTO {
/**
* 用户名
*/
private String username;
/**
* 用户密码
*/
@ApiModelProperty(name = "用户密码,base64加密后的")
private String password;
@ApiModelProperty(name = "登录域名")
private String path;
@ApiModelProperty(name = "手机号码")
private String userPhone;
@ApiModelProperty(name = "验证码")
private String verificationCode;
/** APP包名 */
@ApiModelProperty(name = "APP包名")
private String appMark;
}
@@ -0,0 +1,92 @@
package com.mhd.auth.app.interfaces.facade;
import com.mhd.auth.app.interfaces.dto.LoginDTO;
import com.mhd.auth.app.application.service.TokenLoginApplicationService;
import com.mhd.auth.app.application.service.AppTokenService;
import com.mhd.common.core.domain.entity.R;
import com.mhd.common.core.domain.po.UserPo;
import com.mhd.common.core.utils.JwtUtils;
import com.mhd.common.core.utils.StringUtils;
import com.mhd.common.core.web.controller.BaseController;
import com.mhd.common.security.annotation.RepeatSubmit;
import com.mhd.common.security.auth.AuthUtil;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.system.api.model.LoginUser;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
@Api(tags = "登录接口")
@Slf4j
@RestController
@RequestMapping("/app")
@CrossOrigin
public class AppTokenController extends BaseController {
@Resource
private AppTokenService tokenService;
@Resource
private TokenLoginApplicationService tokenLoginApplicationService;
/**
* @Description 新登录接口
* @Author Alex
* @Date 2022/12/6 23:06
*/
@PostMapping("/login")
@RepeatSubmit
public R<?> loginApi(@RequestBody LoginDTO loginDTO) {
// 用户登录
LoginUser userInfo = tokenLoginApplicationService.loginApi(loginDTO);
// 获取登录token
return R.ok(tokenService.createTokenApi(userInfo),"登录成功");
}
@DeleteMapping("logout")
public R<?> logout(HttpServletRequest request) {
String token = SecurityUtils.getToken(request);
if (StringUtils.isNotEmpty(token)) {
UserPo userPo = SecurityUtils.getLoginUser().getUserPo();
// 删除用户缓存记录
AuthUtil.logoutByToken(token);
// 记录用户退出日志
tokenLoginApplicationService.logout(userPo);
}
return R.ok();
}
@PostMapping("refresh")
public R<?> refresh(HttpServletRequest request) {
LoginUser loginUser = tokenService.getLoginUser(request);
if (StringUtils.isNotNull(loginUser)) {
// 刷新令牌有效期
tokenService.refreshToken(loginUser);
return R.ok();
}
return R.ok();
}
@PostMapping("register")
public R<?> register(@RequestBody LoginDTO loginDTO) {
// 用户注册
tokenLoginApplicationService.register(loginDTO.getUsername(), loginDTO.getPassword());
return R.ok();
}
/**
* @Description wms 新登录接口
* @Author Alex
* @Date 2022/12/6 23:06
*/
@PostMapping("/loginByWms")
@RepeatSubmit
public R<?> loginApiByWms(@RequestBody LoginDTO loginDTO) {
// 用户登录
LoginUser userInfo = tokenLoginApplicationService.loginApiByWms(loginDTO);
// 获取登录token
return R.ok(tokenService.createTokenApi(userInfo),"登录成功");
}
}