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,33 @@
package com.mhd.auth;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import com.mhd.common.security.annotation.EnableRyFeignClients;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* 认证授权中心
*
* @author mhd
*/
@EnableRyFeignClients
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
@EnableFeignClients(basePackages = {"com.mhd", "com.mhd.auth"})
public class MhdAuthApplication
{
public static void main(String[] args)
{
SpringApplication.run(MhdAuthApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 认证授权中心启动成功 ლ(´ڡ`ლ)゙ \n" +
" .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
}
}
@@ -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),"登录成功");
}
}
@@ -0,0 +1,198 @@
package com.mhd.auth.system.controller;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSONObject;
import com.aliyun.oss.ServiceException;
import com.mhd.auth.system.form.LoginBody;
import com.mhd.auth.system.form.RegisterBody;
import com.mhd.auth.system.service.OtherTokenService;
import com.mhd.auth.system.service.SysLoginService;
import com.mhd.auth.system.form.LoginDTO;
import com.mhd.common.core.constant.HttpStatus;
import com.mhd.common.core.constant.SecurityConstants;
import com.mhd.common.core.domain.thirdparty.dingtalk.UserGetuserinfoDTO;
import com.mhd.common.core.feign.ThirdPartyServiceFeign;
import com.mhd.common.core.web.domain.AjaxResult;
import com.mhd.common.log.annotation.Log;
import com.mhd.system.api.UserServiceFeign;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.mhd.common.core.domain.entity.R;
import com.mhd.common.core.utils.JwtUtils;
import com.mhd.common.core.utils.StringUtils;
import com.mhd.common.security.auth.AuthUtil;
import com.mhd.common.security.service.TokenService;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.system.api.model.LoginUser;
import java.util.Map;
/**
* token 控制
*
* @author mhd
*/
@RestController
public class TokenController {
@Resource
private TokenService tokenService;
@Autowired
private SysLoginService sysLoginService;
@Resource
private OtherTokenService otherTokenService;
@Autowired
private ThirdPartyServiceFeign thirdPartyServiceFeign;
@Autowired
private UserServiceFeign userServiceFeign;
@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 RegisterBody registerBody) {
// 用户注册
sysLoginService.register(registerBody.getUsername(), registerBody.getPassword());
return R.ok();
}
/**
* @Description 新登录接口
* @Author Alex
* @Date 2022/12/6 23:06
*/
// @Log(logType = 1,title = "用户登录")
@PostMapping("loginApi")
public R<?> loginApi(@RequestBody LoginDTO loginDTO) {
// 用户登录
LoginUser userInfo = sysLoginService.loginApi(loginDTO);
// 获取登录token
//数字物流本身token获取
Map<String, Object> result = tokenService.createTokenApi(userInfo);
//获取网络货运/多式联运token/获取后市场token
// Object access_token_ntocc = otherTokenService.getNtoccToken("admin","JEAs2SBGNO5894luKsvUog==");
//获取WMS1系统token
// Object access_token_wms1 = otherTokenService.getWms1Token("admin","abcd1234");
//获取WMS2系统token
// Object access_token_wms2 = otherTokenService.getWms2Token("admin","jtom123456");
//获取华夏运力系统token
// Object access_token_huaxia = otherTokenService.getHuaxiaToken("admin","UXExMTExMTE=");
//获取oms系统token
// Object access_token_oms = otherTokenService.getOmsToken("admin","Qq123456@");
// result.put("access_token_ntocc",access_token_ntocc);
// result.put("access_token_wms1",access_token_wms1);
// result.put("access_token_wms2",access_token_wms2);
// result.put("access_token_huaxia",access_token_huaxia);
// result.put("access_token_oms",access_token_oms);
return R.ok(result,"登录成功");
}
/**
* @Description 钉钉小程序免登录接口
* @Author Alex
* @Date 2022/12/6 23:06
*/
// @Log(logType = 1,title = "用户登录")
@GetMapping("dingloginApi")
public R<?> dingloginApi(@RequestParam("code") String code) {
UserGetuserinfoDTO userGetuserinfoDTO=new UserGetuserinfoDTO();
userGetuserinfoDTO.setCode(code);
// 用户登录
//LoginUser userInfo = sysLoginService.loginApi(loginDTO);
AjaxResult ajaxResult=thirdPartyServiceFeign.getuserinfo(userGetuserinfoDTO);
if("200".equals(String.valueOf(ajaxResult.get("code")))){
String dingUserId=ajaxResult.get("data").toString();
if(org.apache.commons.lang.StringUtils.isNotBlank(dingUserId)){
R<LoginUser> userResult =userServiceFeign.getUserByDingUserId(dingUserId, SecurityConstants.INNER);
if (R.FAIL == userResult.getCode()) {
throw new com.mhd.common.core.exception.ServiceException(userResult.getMsg());
}
LoginUser userInfo=userResult.getData();
// 获取登录token
//数字物流本身token获取
Map<String, Object> result = tokenService.createTokenApiDingDing(userInfo);
return R.ok(result,"登录成功");
}else{
return R.fail("获取钉钉用户信息失败");
}
}else{
return R.fail("获取钉钉用户信息失败");
}
//获取网络货运/多式联运token/获取后市场token
// Object access_token_ntocc = otherTokenService.getNtoccToken("admin","JEAs2SBGNO5894luKsvUog==");
//获取WMS1系统token
// Object access_token_wms1 = otherTokenService.getWms1Token("admin","abcd1234");
//获取WMS2系统token
// Object access_token_wms2 = otherTokenService.getWms2Token("admin","jtom123456");
//获取华夏运力系统token
// Object access_token_huaxia = otherTokenService.getHuaxiaToken("admin","UXExMTExMTE=");
//获取oms系统token
// Object access_token_oms = otherTokenService.getOmsToken("admin","Qq123456@");
// result.put("access_token_ntocc",access_token_ntocc);
// result.put("access_token_wms1",access_token_wms1);
// result.put("access_token_wms2",access_token_wms2);
// result.put("access_token_huaxia",access_token_huaxia);
// result.put("access_token_oms",access_token_oms);
}
@PostMapping("/logoutPc")
public R<?> logoutPc(HttpServletRequest request) {
String token = SecurityUtils.getToken(request);
if (StringUtils.isNotEmpty(token)) {
LoginUser loginUser = SecurityUtils.getLoginUser();
// 删除用户缓存记录
AuthUtil.logoutByToken(token);
// 记录用户退出日志
sysLoginService.logout(loginUser);
}
return R.ok();
}
/**
* 刷新token保存在redis的数据
* @param request
* @return
*/
@PostMapping("refreshData")
public R<?> refreshData(HttpServletRequest request) {
LoginUser loginUser = tokenService.refreshData(request);
String token = loginUser.getToken();
LoginUser loginUser1 = sysLoginService.refreshLoginByVerificationCode(loginUser);
loginUser1.setToken(token);
// 刷新令牌有效期
tokenService.refreshTokenData(loginUser1);
return R.ok();
}
@ApiOperation(value = "校验验证码", notes = "校验验证码")
@PostMapping(value = "/checkCode")
public AjaxResult<?> checkCode(@RequestBody LoginDTO loginDTO) {
try {
return AjaxResult.success("操作成功",sysLoginService.checkCode(loginDTO));
} catch (ServiceException e) {
e.printStackTrace();
return AjaxResult.error(HttpStatus.ERROR,"操作失败" + e.getErrorMessage());
} catch (Exception e) {
e.printStackTrace();
return AjaxResult.error(HttpStatus.ERROR,"操作失败" + e.getMessage());
}
}
}
@@ -0,0 +1,23 @@
package com.mhd.auth.system.form;
import com.mhd.common.core.annotation.Excel;
import lombok.Data;
/**
* 用户登录对象
*
* @author mhd
*/
@Data
public class LoginBody
{
/**
* 用户名
*/
private String username;
/**
* 用户密码
*/
private String password;
}
@@ -0,0 +1,41 @@
package com.mhd.auth.system.form;
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 = "用户密码,加密后的")
private String password;
@ApiModelProperty(name = "登录域名")
private String path;
@ApiModelProperty(name = "手机号码")
private String userPhone;
@ApiModelProperty(name = "验证码")
private String verificationCode;
@ApiModelProperty(value = "登录页验证码登录(1-开启,2-关闭)")
private Integer isVerifiedCode;
@ApiModelProperty(value = "短信类型:0.登录模板、1.注册模板、2.忘记密码模板、3-修改密码、5.修改支付密码")
private String smsmode;
@ApiModelProperty(value = "仓库Id")
private Long warehouseId;
}
@@ -0,0 +1,11 @@
package com.mhd.auth.system.form;
/**
* 用户注册对象
*
* @author mhd
*/
public class RegisterBody extends LoginBody
{
}
@@ -0,0 +1,209 @@
package com.mhd.auth.system.service;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mhd.common.core.constant.HttpStatus;
import com.mhd.common.core.exception.ServiceException;
import com.mhd.common.core.utils.AESUtil;
import com.mhd.common.core.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 获取其他系统token
* 网络货运/多式联运
* 后市场
* @author mhd
*/
@Slf4j
@Component
public class OtherTokenService {
//网络货运/多式联运
private static final String ntoccUrl = "https://wanghuo5-test.manhuoda.com/";
//后市场
private static final String marketUrl = "http://ntoc-market.manhuoda.com";
//WMS1
private static final String wms1Url = "http://wms1.manhuoda.com/wms-szwl/loginSzwl";
//WMS2
private static final String wms2Url = "http://wms2.manhuoda.com/wms-api/loginAuth";
//华夏运力
private static final String huaxiaUrl = "http://tms.manhuoda.com";
//oms系统登录
private static final String omsUrl = "http://47.92.229.169:9204/jeecg-boot";
//登录接口地址
private static final String loginUrl = "/jeecg-boot/sys/login";
/**
* 获取网络货运/多式联运登录令牌
* @param username 账号
* @param password 密码 (加密后,需先解密)
* @return 登录后的令牌
*/
public Object getNtoccToken(String username,String password) {
String userPassword = AESUtil.decrypt(password);
log.info("账号"+ username+"登录网货系统");
System.out.println(userPassword);
Map<String,Object> loginParams = new HashMap<>();
loginParams.put("password",userPassword);
loginParams.put("username",username);
//Http调用,请求系统
String url = ntoccUrl + loginUrl;
String jsonParam = JSON.toJSONString(loginParams);
log.info("账号"+ username+"登录参数" + jsonParam);
String result = HttpUtil.post(url,jsonParam);
// String result = "{\"success\":true,\"message\":\"登录成功\",\"code\":200,\"result\":{\"token\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2OTUzNjMxODgsInVzZXJuYW1lIjoiYWRtaW4ifQ.D8zjLFSX65CRkunO6zSLxrjmEzBBullVD-a-dSp6ykY\"},\"timestamp\":1695363188180}\n";
// String result = "{\"success\":false,\"message\":\"用户名或密码错误!\",\"code\":500,\"result\":null,\"timestamp\":1695369871836}";
log.info("账号"+ username+"登录返回参数" + result);
if(StringUtils.isNotEmpty(result)){
if(isJsonString(result)) {
JSONObject jsonObject = JSON.parseObject(result);
if(jsonObject.getInteger("code")== HttpStatus.SUCCESS){
return jsonObject.getJSONObject("result");
}
}
}
return null;
}
public Object getMarketToken(String username, String password) {
log.info("账号"+ username+"登录网货系统");
String userPassword = AESUtil.decrypt(password);
Map<String,Object> loginParams = new HashMap<>();
loginParams.put("password",userPassword);
loginParams.put("username",username);
//Http调用,请求系统
String url = marketUrl + loginUrl;
String jsonParam = JSON.toJSONString(loginParams);
log.info("账号"+ username+"登录参数" + jsonParam);
String result = HttpUtil.post(url,jsonParam);
// String result = "{\"success\":true,\"message\":\"登录成功\",\"code\":200,\"result\":{\"token\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2OTUzNjMxODgsInVzZXJuYW1lIjoiYWRtaW4ifQ.D8zjLFSX65CRkunO6zSLxrjmEzBBullVD-a-dSp6ykY\"},\"timestamp\":1695363188180}\n";
// String result = "{\"success\":false,\"message\":\"用户名或密码错误!\",\"code\":500,\"result\":null,\"timestamp\":1695369871836}";
log.info("账号"+ username+"登录返回参数" + result);
if(StringUtils.isEmpty(result)){
throw new ServiceException("登录失败");
}
JSONObject jsonObject = JSON.parseObject(result);
if(jsonObject.getInteger("code")== HttpStatus.SUCCESS){
return jsonObject.getJSONObject("result");
}else {
throw new ServiceException(jsonObject.getString("message"));
}
}
public Object getWms1Token(String username, String password) {
log.info("账号"+ username+"登录WMS1系统");
Map<String,Object> loginParams = new HashMap<>();
loginParams.put("password",password);
loginParams.put("username",username);
//Http调用,请求系统
String jsonParam = JSON.toJSONString(loginParams);
log.info("账号"+ username+"登录参数" + jsonParam);
String result = HttpUtil.post(wms1Url,jsonParam);
log.info("账号"+ username+"登录返回参数" + result);
if(StringUtils.isNotEmpty(result)){
if(isJsonString(result)) {
JSONObject jsonObject = JSON.parseObject(result);
if(jsonObject.getInteger("code")== HttpStatus.SUCCESS){
return jsonObject.getString("token");
}
}
}
return null;
}
public Object getWms2Token(String username, String password) {
log.info("账号"+ username+"登录WMS1系统");
Map<String,Object> loginParams = new HashMap<>();
loginParams.put("password",password);
loginParams.put("username",username);
//Http调用,请求系统
String jsonParam = JSON.toJSONString(loginParams);
log.info("账号"+ username+"登录参数" + jsonParam);
String result = HttpUtil.post(wms2Url,jsonParam);
log.info("账号"+ username+"登录返回参数" + result);
if(StringUtils.isNotEmpty(result)){
if(isJsonString(result)){
JSONObject jsonObject = JSON.parseObject(result);
if(jsonObject.getInteger("code")== HttpStatus.SUCCESS){
return jsonObject.getString("token");
}
}
}
return null;
}
public Object getHuaxiaToken(String username, String password) {
// String userPassword = AESUtil.decrypt(password);
// log.info("账号"+ username+"登录网货系统(华夏运力)");
// System.out.println(userPassword);
Map<String,Object> loginParams = new HashMap<>();
loginParams.put("password",password);
loginParams.put("username",username);
loginParams.put("isPassword",1);
//Http调用,请求系统
String url = huaxiaUrl + loginUrl;
String jsonParam = JSON.toJSONString(loginParams);
log.info("账号"+ username+"登录参数" + jsonParam);
String result = HttpUtil.post(url,jsonParam);
log.info("账号"+ username+"登录返回参数" + result);
if(StringUtils.isNotEmpty(result)){
if(isJsonString(result)) {
JSONObject jsonObject = JSON.parseObject(result);
if(jsonObject.getInteger("code")== HttpStatus.SUCCESS){
return jsonObject.getJSONObject("result");
}
}
}
return null;
}
public static boolean isJsonString(String jsonString) {
String pattern = "\\{.*\\}|\\[.*\\]";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(jsonString);
return m.matches();
}
public Object getOmsToken(String username, String password) {
Map<String,Object> loginParams = new HashMap<>();
loginParams.put("password",password);
loginParams.put("username",username);
//Http调用,请求系统
String url = omsUrl + "/sys/loginApi";
String jsonParam = JSON.toJSONString(loginParams);
log.info("账号"+ username+"登录参数" + jsonParam);
String result = HttpUtil.post(url,jsonParam);
log.info("账号"+ username+"登录返回参数" + result);
if(StringUtils.isNotEmpty(result)){
if(isJsonString(result)) {
JSONObject jsonObject = JSON.parseObject(result);
if(jsonObject.getInteger("code")== HttpStatus.SUCCESS){
return jsonObject.getJSONObject("result");
}
}
}
return null;
}
}
@@ -0,0 +1,687 @@
package com.mhd.auth.system.service;
import cn.hutool.core.collection.CollUtil;
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.alibaba.fastjson2.JSONObject;
import com.google.common.base.Strings;
import com.mhd.auth.system.form.LoginDTO;
import com.mhd.common.core.constant.*;
import com.mhd.common.core.domain.entity.OrgProductConfig;
import com.mhd.common.core.domain.po.*;
import com.mhd.common.core.domain.po.thirdparty.SysDepartInterfaceInfoPo;
import com.mhd.common.core.domain.thirdparty.SysDepartInterfaceInfoDTO;
import com.mhd.common.core.enums.RoleEnum;
import com.mhd.common.core.exception.digitalLogisticsException.DigitalLogisticsException;
import com.mhd.common.core.exception.digitalLogisticsException.UserError;
import com.mhd.common.core.feign.ThirdPartyServiceFeign;
import com.mhd.common.core.utils.*;
import com.mhd.common.core.utils.ip.IpUtil;
import com.mhd.common.core.utils.sms.CommonConstant;
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.system.api.*;
import com.mhd.system.api.domain.*;
import com.mhd.system.api.domain.mall.SysTenant;
import com.mhd.system.api.domain.mall.UserInfo;
import com.mhd.system.api.domain.mall.UserInfoLoginDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.mhd.common.core.domain.entity.R;
import com.mhd.common.core.enums.UserStatus;
import com.mhd.common.core.exception.ServiceException;
import com.mhd.common.core.utils.ip.IpUtils;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.system.api.model.LoginUser;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 登录校验方法
*
* @author mhd
*/
@Component
@Slf4j
public class SysLoginService {
@Autowired
private AsyncLogService asyncLogService;
@Resource
private RemoteUserService remoteUserService;
@Resource
private OrganizationServiceFeign organizationServiceFeign;
@Resource
private TicketServiceFeign ticketServiceFeign;
@Resource
private UserServiceFeign userServiceFeign;
@Resource
private WlhyServiceFeign wlhyServiceFeign;
@Resource
private RedisService redisService;
@Resource
private ThirdPartyServiceFeign thirdPartyServiceFeign;
@Resource
private SysPasswordService sysPasswordService;
@Autowired
private SystemServiceFeign systemServiceFeign;
@Autowired
private MallServiceFeign mallServiceFeign;
@Autowired
private MallOAuthServiceFeign mallOAuthServiceFeign;
@Autowired
private UpmsServiceFeign upmsServiceFeign;
public void logout(LoginUser loginUser) {
recordLogininfor(loginUser.getUserPo(), 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));
R<?> registerResult = remoteUserService.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.setPort(String.valueOf(ServletUtils.getRequest().getRemotePort()));
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);
}
/**
* @Description 新登录接口
* @Author Alex
* @Date 2022/12/6 23:06
*/
public LoginUser loginApi(LoginDTO loginDTO) {
String username = loginDTO.getUsername();
//用户密码传值
String password = loginDTO.getPassword();
//手机号
String userPhone = loginDTO.getUserPhone();
//验证码
String verificationCode = null;
//登录方式 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
AjaxResult topOrganizationIdR = organizationServiceFeign.getOrganizationByPath(path, SecurityConstants.INNER);
if (ObjectUtil.isNull(topOrganizationIdR) || ObjectUtil.isNull(topOrganizationIdR.get("data"))) {
throw new ServiceException("一级组织不存在异常");//TODO 一级组织不存在异常
}
if (ObjectUtil.isNull(topOrganizationIdR) || ObjectUtil.isNull(topOrganizationIdR.get("data"))) {
Long topOrganizationId = 0L;
//获取用户信息,组装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) || 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(userPo.getDelFlag().toString())) {
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 + " 已停用");
}
//登录页验证码登录
UserConfigSwitchPo userConfigSwitchPo = null;
AjaxResult ajaxResult = systemServiceFeign.getUserConfigSwitchInfoByOrgId(topOrganizationId);
if ("200".equals(String.valueOf(ajaxResult.get("code")))) {
userConfigSwitchPo = com.alibaba.fastjson2.JSONObject.parseObject(JSONObject.toJSONString(ajaxResult.get("data")), UserConfigSwitchPo.class);
}else {
throw new ServiceException("获取开关配置信息失败");
}
if (1 == userConfigSwitchPo.getIsVerifiedCode()) {
verificationCode = loginDTO.getVerificationCode();
}
//校验用户账号密码是否正确
sysPasswordService.validate(userPo, userPassword, 0, verificationCode);
}
else {
SysTenantsPo sysTenantsPo = JSON.parseObject(JSON.toJSONString(topOrganizationIdR.get("data")), SysTenantsPo.class);
Long topOrganizationId = sysTenantsPo.getOrganizationId();
//服务状态:0-无状态,1-开启,2-关闭
Integer tenantsStatus = sysTenantsPo.getTenantsStatus();
if(1!=tenantsStatus){
throw new ServiceException("产品已停用!");
}
if (ObjectUtil.isNull(topOrganizationId)) {
throw new ServiceException("登录用户:" + username + " 组织不存在");
}
//获取用户信息,组装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) || StringUtils.isNull(userResult.getData())) {
recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在", 1);
throw new ServiceException("登录用户:" + username + " 不存在");
}
userInfo = userResult.getData();
//获取用户角色信息,分析用户状态是否正常
UserPo userPo = userResult.getData().getUserPo();
if(ObjectUtil.isNull(userPo)){
topOrganizationId = 0L;
//获取用户信息,组装dto
userDTO.setUserAccount(username);
userDTO.setTopOrganizationId(topOrganizationId);
userDTO.setOrganizationId(topOrganizationId);
userResult = userServiceFeign.getUserByTopOrganizationUserAccount(userDTO, SecurityConstants.INNER);
if (R.FAIL == userResult.getCode()) {
throw new ServiceException(userResult.getMsg());
}
if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData())) {
recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户组织不存在", 1);
throw new ServiceException("登录用户:" + username + " 组织不存在");
}
userInfo = userResult.getData();
//获取用户角色信息,分析用户状态是否正常
userPo = userResult.getData().getUserPo();
}
//判断设否设置登录密码
if (StrUtil.isEmpty(userPo.getUserPassword())) {
recordLogininfor(userPo, Constants.LOGIN_FAIL, "对不起,您的账号未设置登录密码,请先通过验证码进行登录,进行密码设置", 1);
throw new ServiceException("对不起,您的账号:" + username + " 未设置登录密码,请先通过验证码进行登录,进行密码设置");
}
//删除标记:0-无状态,1-正常,2-已删除
if (ObjectUtil.isNull(userPo) || UserStatus.DELETED.getCode().equals(userPo.getDelFlag().toString())) {
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 + " 已停用");
}
//登录页验证码登录
UserConfigSwitchPo userConfigSwitchPo = null;
AjaxResult ajaxResult = systemServiceFeign.getUserConfigSwitchInfoByOrgId(topOrganizationId);
if ("200".equals(String.valueOf(ajaxResult.get("code")))) {
userConfigSwitchPo = com.alibaba.fastjson2.JSONObject.parseObject(JSONObject.toJSONString(ajaxResult.get("data")), UserConfigSwitchPo.class);
}else {
throw new ServiceException("获取开关配置信息失败");
}
if (1 == userConfigSwitchPo.getIsVerifiedCode()) {
verificationCode = loginDTO.getVerificationCode();
}
//校验用户账号密码是否正确
sysPasswordService.validate(userPo, userPassword, 0, verificationCode);
}
}
//保存用户登录
UserUpdateDTO userUpdateDTO = new UserUpdateDTO();
userUpdateDTO.setLastLoginTime(new Date());
userUpdateDTO.setLastLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
userUpdateDTO.setUserName(username);
userServiceFeign.updateWhenLogin(userUpdateDTO, SecurityConstants.INNER);
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);
//查询当前登录企业绑定组织关系
R<List<OrganizationCorrelationPO>> listByOrganizationIdR = organizationServiceFeign.findListByOrganizationId(userInfo.getUserPo().getOrganizationId());
if (R.FAIL == listByOrganizationIdR.getCode()){
throw new ServiceException(listByOrganizationIdR.getMsg());
}
//查询产品中台,将登录用户所在组织配置的产品存到缓存中。
//处理网络货运基本信息
//处理商城基本信息
processWLHYInformation(loginType, "1", userNameOrUserPhone, userInfo);
List<OrganizationCorrelationPO> organizationCorrelationPOList = listByOrganizationIdR.getData().stream().filter(p -> 1 == p.getAssociationPlatformType()).collect(Collectors.toList());
//判断当前登录企业是否绑定票务平台,绑定才查询
if (!organizationCorrelationPOList.isEmpty()){
R<List<EnterpriseAccessPO>> ticketEnterprisePOR = ticketServiceFeign.getEnterprisePoByOrganizationId(userInfo.getUserPo().getOrganizationId());
if (R.FAIL == ticketEnterprisePOR.getCode()){
throw new ServiceException(ticketEnterprisePOR.getMsg());
}
userInfo.setEnterpriseAccessPO(ticketEnterprisePOR.getData());
}
//查询用户角色
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.isEmpty()){
userInfo.setRoleList(rolePOS.stream().map(RolePO::getRoleName).collect(Collectors.toList()));
userInfo.setRoleIdList(rolePOS.stream().map(RolePO::getRoleId).collect(Collectors.toList()));
}else {
throw new ServiceException("账号未授权角色信息!");
}
}
//判断是否选择了仓库 选择了仓库将登录信息赋值进去
AssociationWarehouseFeign associationWarehouseFeign = new AssociationWarehouseFeign();
associationWarehouseFeign.setCorrelationId(userInfo.getUserPo().getUserId());
systemServiceFeign.setWarehouseInfo(associationWarehouseFeign);
recordLogininfor(userInfo.getUserPo(), Constants.LOGIN_SUCCESS, "登录成功", 1);
return userInfo;
}
public String processWLHYInformation(String loginType, String clientType, String userNameOrUserPhone, LoginUser userInfo) {
String key = CacheConstants.ORG_PRODUCT_KEY + userInfo.getUserPo().getTopOrganizationId();
//从三方配置表中取值
SysDepartInterfaceInfoDTO sysDepartInterfaceInfoDTO = new SysDepartInterfaceInfoDTO();
sysDepartInterfaceInfoDTO.setTopOrganizationId(userInfo.getUserPo().getTopOrganizationId());
sysDepartInterfaceInfoDTO.setInterfaceType("wlhy");
sysDepartInterfaceInfoDTO.setInterfaceTypeKey("has_wlhy");
List<SysDepartInterfaceInfoPo> sysDepartInterfaceInfoPos = thirdPartyServiceFeign.queryListByFeign(sysDepartInterfaceInfoDTO);
Integer wlhyFlag = 2;
if (CollUtil.isNotEmpty(sysDepartInterfaceInfoPos)) {
String interfaceTypeValue = sysDepartInterfaceInfoPos.get(0).getInterfaceTypeValue();
if (StrUtil.equals("1", interfaceTypeValue)) {
wlhyFlag = 1;
}
}
//从三方配置表中取值
sysDepartInterfaceInfoDTO.setTopOrganizationId(userInfo.getUserPo().getTopOrganizationId());
sysDepartInterfaceInfoDTO.setInterfaceType("mall");
sysDepartInterfaceInfoDTO.setInterfaceTypeKey("has_mall");
List<SysDepartInterfaceInfoPo> sysDepartInterfaceInfoTwo = thirdPartyServiceFeign.queryListByFeign(sysDepartInterfaceInfoDTO);
int mallFlag = 2;
if (CollUtil.isNotEmpty(sysDepartInterfaceInfoTwo)) {
String interfaceTypeValue = sysDepartInterfaceInfoTwo.get(0).getInterfaceTypeValue();
if (StrUtil.equals("1", interfaceTypeValue)) {
mallFlag = 1;
}
}
OrgProductConfig orgProductConfigFlag = new OrgProductConfig();
orgProductConfigFlag.setWlhyFlag(wlhyFlag);
orgProductConfigFlag.setMallFlag(mallFlag);
redisService.setCacheObject(key, orgProductConfigFlag);
if (wlhyFlag == 1) {
//获取网货登录用户基本信息
SysLoginModel sysLoginModel = new SysLoginModel();
if (StrUtil.equals("1", loginType)) {
sysLoginModel.setUsername(userNameOrUserPhone);
} else if (StrUtil.equals("2", loginType)) {
sysLoginModel.setUserPhone(userNameOrUserPhone);
}
R<WlhyLoginUser> wlhyLoginUserR = wlhyServiceFeign.getWlhyUserInfo(sysLoginModel);
if (wlhyLoginUserR.getCode() == R.SUCCESS) {
userInfo.setWlhyLoginUser(wlhyLoginUserR.getData());
}
}
if(mallFlag == 1){
/*单点登录,获取商城鉴权
* 根据用户角色判断需要鉴权的服务,
* 商城管理端:系统管理员、租户管理员、店铺管理员、店铺员工
* 商城用户端:承运人角色,车队长角色,运输企业角色
*/
AjaxResult roleListAjaxResult = userServiceFeign.getRoleListByUserId(userInfo.getUserPo().getUserId());
if ("200".equals(String.valueOf(roleListAjaxResult.get("code")))) {
List<RolePO> rolePOS = new ArrayList<>();
if (ObjectUtil.isNotNull(roleListAjaxResult.get("data"))){
rolePOS = JSONUtil.toList(JSONUtil.toJsonStr(roleListAjaxResult.get("data")), RolePO.class);
}
//获取用户角色列表,判断用户角色
List<String> rolsCodes = rolePOS.stream().map(RolePO::getRoleCode).collect(Collectors.toList());
//考虑app刚注册没有角色,登录的情况
//登录类型:clientType 1-PC端登录 2-移动端登录
if(StrUtil.equals("2", clientType) && !rolsCodes.contains(RoleEnum.PLAT_ADMIN.getCode()) && (rolePOS.isEmpty() || rolsCodes.contains(RoleEnum.CAPTAIN.getCode()) || rolsCodes.contains(RoleEnum.MUST.getCode())
|| rolsCodes.contains(RoleEnum.DRIVER.getCode())
|| rolsCodes.contains(RoleEnum.CARRIER.getCode()))){
String tenantsId = String.valueOf(userInfo.getOrganizationPo().getTenantsId());
R<SysTenant> sysTenantR = upmsServiceFeign.getBySzwlTenantId(tenantsId, "Y");
if(0 != sysTenantR.getCode()){
throw new ServiceException("获取商城租户信息失败:" + sysTenantR.getMsg());
}
SysTenant sysTenant = sysTenantR.getData();
UserInfoLoginDTO userInfoLoginDTO = new UserInfoLoginDTO();
userInfoLoginDTO.setPhone(userNameOrUserPhone);
R<UserInfo> userInfoR = mallServiceFeign.login(userInfoLoginDTO,"H5",String.valueOf(sysTenant.getTenantId()));
if(0 != userInfoR.getCode()){
throw new ServiceException("获取商城鉴权失败:" + userInfoR.getMsg());
}
UserInfo userInfoLogin = userInfoR.getData();
log.info("商城用户端鉴权返回结果:{}",JSONUtil.toJsonStr(userInfoLogin));
userInfo.setThirdSession(userInfoLogin.getThirdSession());
userInfo.setMallTenantId(userInfoLogin.getTenantId());
//PC端登录
}else if (StrUtil.equals("1", loginType) && (rolsCodes.contains(RoleEnum.MALL_PLAT_ADMIN.getCode()) || rolsCodes.contains(RoleEnum.STORE_ADMIN.getCode()) || rolsCodes.contains(RoleEnum.SUPER_ADMIN.getCode()))){
//商城管理端
Map<String, String> params = new HashMap<>();
params.put("username",userInfo.getUserPo().getUserAccount());
params.put("password","123456");
params.put("grant_type","password");
params.put("scope","server");
String authorization = "Basic " + Base64Utils.encode64("admin:admin");
String result = mallOAuthServiceFeign.oauthToken(params, authorization);
log.info("商城管理端鉴权返回结果:{}",result);
if(StringUtils.isBlank(result)){
throw new ServiceException("获取商城鉴权失败:" + result);
}
userInfo.setMallOAuthToken(JSONUtil.toBean(JSONUtil.parseObj(result), MallOAuthToken.class));
}
}
}
return null;
}
/**
* @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();
//用户信息
LoginUser userInfo = new LoginUser();
// 手机号、验证码为空 错误
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, SecurityConstants.INNER);
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());
}
if (ObjectUtil.isNull(userResult) || ObjectUtil.isNull(userResult.getData()) || ObjectUtil.isNull(userResult.getData().getUserPo())) {
recordLogininfor(userPhone, Constants.LOGIN_FAIL, "登录用户不存在", 1);
throw new ServiceException("登录用户:" + userPhone + " 不存在");
}
userInfo = userResult.getData();
//获取用户角色信息,分析用户状态是否正常
UserPo userPo = userResult.getData().getUserPo();
//删除标记:0-无状态,1-正常,2-已删除
if (ObjectUtil.isNull(userPo) || UserStatus.DELETED.getCode().equals(userPo.getDelFlag().toString())) {
recordLogininfor(userPo, Constants.LOGIN_FAIL, "对不起,您的账号不存在或已被删除", 1);
throw new ServiceException("对不起,您的账号:" + userPhone + " 不存在或已被删除");
}
//用户状态:0-无状态,1-正常,2-锁定
if (UserStatus.DELETED.getCode().equals(userPo.getUserStatus().toString())) {
recordLogininfor(userPo, Constants.LOGIN_FAIL, "用户已停用,请联系管理员", 1);
throw new ServiceException("对不起,您的账号:" + userPhone + " 已停用");
}
//校验验证码是否正确
sysPasswordService.validate(userPo, verificationCode, 1, null);
return userInfo;
}
/**
* @Description 验证码登录(刷新数据使用)
* @Author Alex
* @Date 2022/12/9 15:44
*/
public LoginUser refreshLoginByVerificationCode(LoginUser loginUser) {
UserPo userPo1 = loginUser.getUserPo();
//手机号
String userPhone = userPo1.getUserPhone();
//获取用户信息,组装dto
UserDTO userDTO = new UserDTO();
userDTO.setUserPhone(userPhone);
userDTO.setTopOrganizationId(userPo1.getTopOrganizationId());
userDTO.setOrganizationId(userPo1.getTopOrganizationId());
// 查询用户信息,查询组织下用户是否存在
R<LoginUser> userResult = userServiceFeign.getUserByTopOrganizationUserPhone(userDTO, SecurityConstants.INNER);
if (R.FAIL == userResult.getCode()) {
throw new ServiceException(userResult.getMsg());
}
LoginUser userInfo = userResult.getData();
loginUser.setUserPo(userInfo.getUserPo());
loginUser.setUserDriverPo(userInfo.getUserDriverPo());
loginUser.setUserShipperPo(userInfo.getUserShipperPo());
R<OrganizationPo> organizationInfo = organizationServiceFeign.getInfoForIdList(loginUser.getUserPo().getOrganizationId());
if (ObjectUtil.isNull(organizationInfo) || ObjectUtil.isNull(organizationInfo.getData())) {
throw new ServiceException("登录用户组织不存在");
}
OrganizationPo data = organizationInfo.getData();
loginUser.setOrganizationPo(data);
//查询当前登录企业绑定组织关系
R<List<OrganizationCorrelationPO>> listByOrganizationIdR = organizationServiceFeign.findListByOrganizationId(loginUser.getUserPo().getOrganizationId());
if (R.FAIL == listByOrganizationIdR.getCode()){
throw new ServiceException(listByOrganizationIdR.getMsg());
}
List<OrganizationCorrelationPO> organizationCorrelationPOList = listByOrganizationIdR.getData().stream().filter(p -> 1 == p.getAssociationPlatformType()).collect(Collectors.toList());
//判断当前登录企业是否绑定票务平台,绑定才查询
if (!organizationCorrelationPOList.isEmpty()){
R<List<EnterpriseAccessPO>> ticketEnterprisePOR = ticketServiceFeign.getEnterprisePoByOrganizationId(loginUser.getUserPo().getOrganizationId());
if (R.FAIL == ticketEnterprisePOR.getCode()){
throw new ServiceException(ticketEnterprisePOR.getMsg());
}
loginUser.setEnterpriseAccessPO(ticketEnterprisePOR.getData());
}
//查询产品中台,将登录用户所在组织配置的产品存到缓存中。
//处理网络货运基本信息 默认
processWLHYInformation("2", "", userPhone, loginUser);
//查询用户角色
AjaxResult roleListAjaxResult = userServiceFeign.getRoleListByUserId(loginUser.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){
loginUser.setRoleList(rolePOS.stream().map(RolePO::getRoleName).collect(Collectors.toList()));
loginUser.setRoleIdList(rolePOS.stream().map(RolePO::getRoleId).collect(Collectors.toList()));
}
}
return loginUser;
}
/**
* 校验验证码是否失效
* @param loginDTO
* @return
*/
public boolean checkCode(LoginDTO loginDTO) {
if(!StringUtils.isNotBlank(loginDTO.getUserPhone())){
throw new ServiceException("手机号不能为空");
}
if(!StringUtils.isNotBlank(loginDTO.getVerificationCode())){
throw new ServiceException("验证码不能为空");
}
if(!StringUtils.isNotBlank(loginDTO.getSmsmode())){
throw new ServiceException("验证码类型不能为空");
}
String key;
String smsmode = loginDTO.getSmsmode();
if (CommonConstant.SMS_TPL_TYPE_0.equals(smsmode)) {
key = CacheConstants.SMS_LOGIN + loginDTO.getUserPhone();
}else if(CommonConstant.SMS_TPL_TYPE_1.equals(smsmode)){
key = CacheConstants.SMS_REGISTER + loginDTO.getUserPhone();
}else if(CommonConstant.SMS_TPL_TYPE_2.equals(smsmode)) {
key = CacheConstants.SMS_FORGET + loginDTO.getUserPhone();
} else if(CommonConstant.SMS_TPL_TYPE_3.equals(smsmode)) {
key = CacheConstants.SMS_CHANGE + loginDTO.getUserPhone();
}else if(CommonConstant.SMS_TPL_TYPE_5.equals(smsmode)) {
key = CacheConstants.SMS_PAY_CHANGE + loginDTO.getUserPhone();
}else {
throw new ServiceException("暂无短信模板");
}
Object object = redisService.getCacheObject(key) == null ? "" : redisService.getCacheObject(key);
return ObjectUtil.equal(String.valueOf(object), loginDTO.getVerificationCode()) || ObjectUtil.equal(loginDTO.getVerificationCode(), SmsConstants.universalCode);
}
}
@@ -0,0 +1,291 @@
package com.mhd.auth.system.service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.mhd.common.core.constant.CacheConstants;
import com.mhd.common.core.constant.Constants;
import com.mhd.common.core.constant.SecurityConstants;
import com.mhd.common.core.constant.SmsConstants;
import com.mhd.common.core.domain.po.UserPo;
import com.mhd.common.core.domain.po.thirdparty.SysDepartInterfaceInfoPo;
import com.mhd.common.core.domain.thirdparty.SysDepartInterfaceInfoDTO;
import com.mhd.common.core.exception.ServiceException;
import com.mhd.common.core.feign.ThirdPartyServiceFeign;
import com.mhd.common.core.utils.ServletUtils;
import com.mhd.common.core.utils.StringUtils;
import com.mhd.common.core.utils.RequestHeaderUtil;
import com.mhd.common.core.utils.ip.IpUtil;
import com.mhd.common.core.utils.ip.IpUtils;
import com.mhd.common.log.service.AsyncLogService;
import com.mhd.common.redis.service.RedisService;
import com.mhd.common.security.utils.password.PasswordUtil;
import com.mhd.system.api.RemoteLogService;
import com.mhd.system.api.domain.SysLogininforPo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* @author ZhouGY
* @title SysPasswordService
* @description: 登录密码方法
* @date 2023/12/26 15:33
**/
@Component
public class SysPasswordService
{
@Autowired
private RedisService redisService;
@Autowired
private ThirdPartyServiceFeign thirdPartyServiceFeign;
@Autowired
private AsyncLogService asyncLogService;
/**
* 登录账户密码错误次数缓存键名
*
* @param username 用户名
* @return 缓存键key
*/
private String getCacheKey(String username) {
return CacheConstants.PWD_ERR_CNT_KEY + username;
}
/**
* @description 校验用户账号密码是否正确
* @author ZhouGY
* @date 2023/12/26 16:23
* @param userPo 用户信息
* @param password 密码或者验证码
* @param loginType 登录类型:0-密码 1-验证码
* @param verificationCode 验证码登录时的验证码
*/
public void validate(UserPo userPo, String password, Integer loginType, String verificationCode) {
String username = userPo.getUserAccount();
Integer retryCount = redisService.getCacheObject(getCacheKey(username));
if (retryCount == null) {
retryCount = 0;
}
//TODO 从三方配置表中取值
SysDepartInterfaceInfoDTO sysDepartInterfaceInfoDTO = new SysDepartInterfaceInfoDTO();
sysDepartInterfaceInfoDTO.setTopOrganizationId(userPo.getTopOrganizationId());
sysDepartInterfaceInfoDTO.setInterfaceType("login");
sysDepartInterfaceInfoDTO.setInterfaceTypeKey("maxRetryCount");
List<SysDepartInterfaceInfoPo> sysDepartInterfaceInfoPos = thirdPartyServiceFeign.queryListByFeign(sysDepartInterfaceInfoDTO);
if (sysDepartInterfaceInfoPos.isEmpty()){
String errMsg = "缺少登录信息配置,请联系管理员";
recordLogininfor(userPo, Constants.LOGIN_FAIL, errMsg, 1);
throw new ServiceException(errMsg);
}
SysDepartInterfaceInfoPo sysDepartInterfaceInfoPo = sysDepartInterfaceInfoPos.get(0);
Integer maxRetryCount = Integer.valueOf(sysDepartInterfaceInfoPo.getInterfaceTypeValue());
sysDepartInterfaceInfoDTO.setInterfaceTypeKey("lockTime");
sysDepartInterfaceInfoPos = thirdPartyServiceFeign.queryListByFeign(sysDepartInterfaceInfoDTO);
if (sysDepartInterfaceInfoPos.isEmpty()){
String errMsg = "缺少登录信息配置,请联系管理员";
recordLogininfor(userPo, Constants.LOGIN_FAIL, errMsg, 1);
throw new ServiceException(errMsg);
}
sysDepartInterfaceInfoPo = sysDepartInterfaceInfoPos.get(0);
Long lockTime = Long.valueOf(sysDepartInterfaceInfoPo.getInterfaceTypeValue());
if (retryCount >= maxRetryCount){
String errMsg = String.format("密码输入错误%s次,帐户锁定%s分钟", maxRetryCount, lockTime);
recordLogininfor(userPo, Constants.LOGIN_FAIL, errMsg, 1);
throw new ServiceException(errMsg);
}
if (loginType == 0) { //密码登录
//登录页验证码登录
if (StrUtil.isNotEmpty(verificationCode)) {
if (!matchesCode(userPo, verificationCode)){
retryCount = retryCount + 1;
redisService.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES);
recordLogininfor(userPo, Constants.LOGIN_FAIL, "验证码错误", 1);
throw new ServiceException("验证码错误");
}
}
if (matchesPassword(userPo, password)){
retryCount = retryCount + 1;
redisService.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES);
recordLogininfor(userPo, Constants.LOGIN_FAIL, "用户密码错误", 1);
throw new ServiceException("用户不存在/密码错误");
}
}else if (loginType == 1 && !matchesCode(userPo, password)) { //验证码登录
retryCount = retryCount + 1;
redisService.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES);
recordLogininfor(userPo, Constants.LOGIN_FAIL, "验证码错误", 1);
throw new ServiceException("验证码错误");
} else {
clearLoginRecordCache(username);
}
}
/**
* @description 校验密码是否正确
* @author ZhouGY
* @date 2023/12/26 16:01
* @param userPo
* @param rawPassword
* @return boolean
*/
public boolean matchesPassword(UserPo userPo, String rawPassword) {
return !PasswordUtil.matchesPassword(userPo.getUserAccount(), rawPassword, userPo.getUserSalt(), userPo.getUserPassword());
}
/**
* @description 验证验证码是否有误
* @author ZhouGY
* @date 2023/12/29 11:49
* @param userPo
* @param password
*/
public boolean matchesCode(UserPo userPo, String password){
String key = CacheConstants.SMS_LOGIN + userPo.getUserPhone();
Object object = redisService.getCacheObject(key) == null ? "" : redisService.getCacheObject(key);
return ObjectUtil.equal(String.valueOf(object), password) || ObjectUtil.equal(password, SmsConstants.universalCode);
}
/**
* @description 清除计数
* @author ZhouGY
* @date 2023/12/26 16:12
* @param loginName
*/
public void clearLoginRecordCache(String loginName) {
if (redisService.hasKey(getCacheKey(loginName))) {
redisService.deleteObject(getCacheKey(loginName));
}
}
/**
* 记录登录信息
*
* @param username 用户名
* @param status 状态
* @param message 消息内容
* @return
*/
// public void recordLogininfor(String username, String status, String message) {
// SysLogininfor logininfor = new SysLogininfor();
// logininfor.setUserAccount(username);
// logininfor.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
// logininfor.setMsg(message);
// // 日志状态
// 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);
// }
// remoteLogService.saveLogininfor(logininfor, SecurityConstants.INNER);
// }
/**
* 记录登录信息
*/
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);
}
/**
* @description 校验用户账号密码是否正确
* @author ZhouGY
* @date 2023/12/26 16:23
* @param userPo 用户信息
* @param password 密码或者验证码
* @param loginType 登录类型:0-密码 1-验证码
*/
public void validateByWms(UserPo userPo, String password, Integer loginType) {
Map<String, Object> objectMap = statisticRetryCount(userPo);
Integer retryCount = (Integer) objectMap.get("retryCount");
Long lockTime = (Long) objectMap.get("lockTime");
String username = userPo.getUserAccount();
if (loginType == 0 && matchesPassword(userPo, password)) { //密码登录
retryCount = retryCount + 1;
redisService.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES);
recordLogininfor(userPo, Constants.LOGIN_FAIL, "用户密码错误", 1);
throw new ServiceException("用户不存在/密码错误");
}else if (loginType == 1 && !matchesCode(userPo, password)) { //验证码登录
retryCount = retryCount + 1;
redisService.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES);
recordLogininfor(userPo, Constants.LOGIN_FAIL, "验证码错误", 1);
throw new ServiceException("验证码错误");
} else {
clearLoginRecordCache(username);
}
}
/**
* @description 统计错误重试次数及获取失效时间
* @author ZhouGY
* @date 2024/6/12 17:31
* @param userPo
* @return Integer
*/
private Map<String, Object> statisticRetryCount(UserPo userPo){
Map<String, Object> objectMap = new HashMap<>();
String username = userPo.getUserAccount();
Integer retryCount = redisService.getCacheObject(getCacheKey(username));
if (retryCount == null) {
retryCount = 0;
}
//TODO 从三方配置表中取值
SysDepartInterfaceInfoDTO sysDepartInterfaceInfoDTO = new SysDepartInterfaceInfoDTO();
sysDepartInterfaceInfoDTO.setTopOrganizationId(userPo.getTopOrganizationId());
sysDepartInterfaceInfoDTO.setInterfaceType("login");
sysDepartInterfaceInfoDTO.setInterfaceTypeKey("maxRetryCount");
List<SysDepartInterfaceInfoPo> sysDepartInterfaceInfoPos = thirdPartyServiceFeign.queryListByFeign(sysDepartInterfaceInfoDTO);
if (sysDepartInterfaceInfoPos.isEmpty()){
String errMsg = "缺少登录信息配置,请联系管理员";
recordLogininfor(userPo, Constants.LOGIN_FAIL, errMsg, 1);
throw new ServiceException(errMsg);
}
SysDepartInterfaceInfoPo sysDepartInterfaceInfoPo = sysDepartInterfaceInfoPos.get(0);
Integer maxRetryCount = Integer.valueOf(sysDepartInterfaceInfoPo.getInterfaceTypeValue());
sysDepartInterfaceInfoDTO.setInterfaceTypeKey("lockTime");
sysDepartInterfaceInfoPos = thirdPartyServiceFeign.queryListByFeign(sysDepartInterfaceInfoDTO);
if (sysDepartInterfaceInfoPos.isEmpty()){
String errMsg = "缺少登录信息配置,请联系管理员";
recordLogininfor(userPo, Constants.LOGIN_FAIL, errMsg, 1);
throw new ServiceException(errMsg);
}
sysDepartInterfaceInfoPo = sysDepartInterfaceInfoPos.get(0);
Long lockTime = Long.valueOf(sysDepartInterfaceInfoPo.getInterfaceTypeValue());
if (retryCount >= maxRetryCount){
String errMsg = String.format("密码输入错误%s次,帐户锁定%s分钟", maxRetryCount, lockTime);
recordLogininfor(userPo, Constants.LOGIN_FAIL, errMsg, 1);
throw new ServiceException(errMsg);
}
objectMap.put("retryCount", retryCount);
objectMap.put("lockTime", lockTime);
return objectMap;
}
}
+10
View File
@@ -0,0 +1,10 @@
Spring Boot Version: ${spring-boot.version}
Spring Application Name: ${spring.application.name}
_ _ _
(_) | | | |
_ __ _ _ ___ _ _ _ ______ __ _ _ _ | |_ | |__
| '__|| | | | / _ \ | | | || ||______| / _` || | | || __|| '_ \
| | | |_| || (_) || |_| || | | (_| || |_| || |_ | | | |
|_| \__,_| \___/ \__, ||_| \__,_| \__,_| \__||_| |_|
__/ |
|___/
+27
View File
@@ -0,0 +1,27 @@
# Tomcat
server:
port: 9200
# Spring
spring:
application:
# 应用名称
name: mhd-auth
profiles:
# 环境配置
active: dev
cloud:
nacos:
discovery:
#server-addr: 192.168.0.69:8848
server-addr: 127.0.0.1:8848
#server-addr: 116.204.23.92:8848
namespace: 4dd3256a-22c0-42db-9af1-de513a05c6a9
config:
# 配置中心地址
#server-addr: 192.168.0.69:8848
server-addr: 127.0.0.1:8848
#server-addr: 116.204.23.92:8848
# 锁定server端的配置文件(读取它的配置项)
namespace: 4dd3256a-22c0-42db-9af1-de513a05c6a9
group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置
file-extension: yml #默认properties
+74
View File
@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 -->
<property name="log.path" value="logs/mhd-auth" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.mhd" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
</configuration>