package cn.com.goldenwater.dcproj.service.impl.login; import cn.com.goldenwater.core.web.BaseResponse; import cn.com.goldenwater.dcproj.constValue.Constants; import cn.com.goldenwater.dcproj.dao.BisInspOrgDao; import cn.com.goldenwater.dcproj.dao.GwStaticUserDao; import cn.com.goldenwater.dcproj.dto.LoginDto; import cn.com.goldenwater.dcproj.model.BisInspAll; import cn.com.goldenwater.dcproj.model.BisInspAllRlationPers; import cn.com.goldenwater.dcproj.model.BisInspLoginInfo; import cn.com.goldenwater.dcproj.model.BisInspOrg; import cn.com.goldenwater.dcproj.model.GwStaticUser; import cn.com.goldenwater.dcproj.param.BisInspAllRlationPersParam; import cn.com.goldenwater.dcproj.param.BisInspOrgParam; import cn.com.goldenwater.dcproj.service.BisInspAllRlationPersService; import cn.com.goldenwater.dcproj.service.BisInspLoginInfoService; import cn.com.goldenwater.dcproj.service.LoginService; import cn.com.goldenwater.dcproj.service.OlBisInspOrgService; import cn.com.goldenwater.dcproj.service.impl.system.OrganizationTreeImpl; import cn.com.goldenwater.dcproj.util.Base64Util; import cn.com.goldenwater.dcproj.utils.Builder; import cn.com.goldenwater.dcproj.utils.IpUtils; import cn.com.goldenwater.dcproj.utils.JWTTokenUtil; import cn.com.goldenwater.dcproj.utils.LogUtils; import cn.com.goldenwater.dcproj.utils.MD5; import cn.com.goldenwater.dcproj.utils.ServletUtils; import cn.com.goldenwater.dcproj.utils.UserMsgSectrityUtils; import cn.com.goldenwater.dcproj.utils.VerifyCodeUtils; import cn.com.goldenwater.dcproj.utils.aesUtil; import cn.com.goldenwater.id.util.UuidUtil; import cn.com.goldenwater.util.common.IPUtils; import eu.bitwalker.useragentutils.UserAgent; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import java.time.temporal.ChronoUnit; import java.util.Date; import java.util.List; import java.util.concurrent.TimeUnit; import static cn.com.goldenwater.core.web.BaseController.buildFailResponse; import static cn.com.goldenwater.core.web.BaseController.buildSuccessResponse; /** * @author: LinQiLong * @create: 2021/10/27 11:27 */ @Service public class LoginServiceImpl implements LoginService { private Logger logger = LoggerFactory.getLogger(getClass()); @Value("${intercept.enable}") public Boolean enterceptEnable; @Value("${smsCode}") private String smsCode; @Autowired private BisInspAllRlationPersService bisInspAllRlationPersService; @Autowired private RedisTemplate redisTemplate; @Autowired private GwStaticUserDao gwStaticUserDao; @Autowired private OrganizationTreeImpl organizationTree; @Autowired private BisInspOrgDao bisInspOrgDao; @Autowired private OlBisInspOrgService olBisInspOrgService; @Value("${sc.login.enabled:true}") private Boolean scLoginEnabled; @Autowired private BisInspLoginInfoService bisInspLoginInfoService; @Override public BaseResponse login(LoginDto loginDto, HttpServletRequest request) { String ip = IPUtils.getIpAddr(request); String blackListKey = "blackList:" + loginDto.getPhone() + ":" + ip; String blackIp = (String) redisTemplate.opsForValue().get(blackListKey); if (loginDto.getPhone().equals(blackIp)) { return buildFailResponse(9991, "检测到该手机号登录过于频繁,可能存在恶意操作,系统已将手机用户暂时列入黑名单,请1小时后再试!"); } // String origin = request.getHeader("Origin"); // String referer = request.getHeader("Referer"); // if (!referer.startsWith(origin)) { // return buildFailResponse(1005,"请求网址不同"); // } if (loginDto.getCode().length() != 6) { return buildFailResponse("验证码有误!"); } BisInspAllRlationPers p = bisInspAllRlationPersService.getBy(Builder.of(BisInspAllRlationPersParam::new) .with(BisInspAllRlationPersParam::setMobilenumb, loginDto.getPhone()) .build()); if (p == null) { return buildFailResponse(1002, "该手机号尚未注册", "", ""); } //如果是广东用户手机登录提示停用 logger.info("login--------------------------------------p.getProvince():" + p.getProvince() + "--------------------------------------------------------"); if (p.getProvince().equals("440000000000")) { return buildFailResponse(1002, "广东暂停使用", "", ""); } //省级平台禁用四川用户登录,启用本地平台 if (!scLoginEnabled) { if (p.getProvince().substring(0, 2).equals("51")) { return buildFailResponse(10015, "四川省用户停用此平台,请访问本地部署平台。系统地址:http://101.207.130.194:37210", "", ""); } } // 根据phone-code获取用户信息 BisInspAllRlationPers bisInspAllRlationPers = bisInspAllRlationPersService.loginByCode(loginDto.getPhone(), loginDto.getCode()); boolean logincode = true; if (bisInspAllRlationPers == null) { GwStaticUser gwStaticUser = gwStaticUserDao.get(loginDto.getPhone()); if (gwStaticUser != null) { // 判断是否与固定验证码相同,相同时获取用户信息 if (smsCode.equals(loginDto.getCode())) { bisInspAllRlationPers = bisInspAllRlationPersService.getBy(Builder.of(BisInspAllRlationPersParam::new) .with(BisInspAllRlationPersParam::setMobilenumb, loginDto.getPhone()) .build()); logincode = false; } } } //发送信息成功后记录数据 if (logincode) { String yzm = (String) redisTemplate.opsForValue().get(loginDto.getPhone()); if (StringUtils.isBlank(yzm)) { return buildFailResponse("图片验证码已经过期,请重新验证!!"); } String[] arrays = yzm.split("_"); //验证码为arrays[0] String yzmReal = (String) redisTemplate.opsForValue().get(arrays[1]); if (StringUtils.isBlank(yzm) || "null".equals(yzm) || yzmReal == null || !yzmReal.equals(arrays[0])) { return buildFailResponse("图片验证码已经过期,请重新输入!!"); } } if (bisInspAllRlationPers == null) { return loginFailureDual(loginDto.getPhone(), ip); } bisInspAllRlationPers.setPwd(null); bisInspAllRlationPers = getBisInspAllRlations(bisInspAllRlationPers); BisInspAllRlationPers pers = new BisInspAllRlationPers(); pers.setGuid(bisInspAllRlationPers.getGuid()); pers.setLoginTm(new Date()); if (StringUtils.isBlank(bisInspAllRlationPers.getPersType())) { bisInspAllRlationPers.setPersType("3"); pers.setPersType("3"); } bisInspAllRlationPersService.update(pers); String uuid = UuidUtil.uuid(); //bisInspAllRlationPersService.sendChannel(uuid, bisInspAllRlationPers, request, PlusEnum.ADD.getNumber()); String accessToken = JWTTokenUtil.sign(bisInspAllRlationPersService.getLoginUser(bisInspAllRlationPers), bisInspAllRlationPers.getGuid()); redisTemplate.opsForValue().set(uuid, accessToken, JWTTokenUtil.maxAge, TimeUnit.MILLISECONDS); redisTemplate.opsForValue().set(uuid + bisInspAllRlationPers.getGuid(), accessToken, JWTTokenUtil.refreshmaxAge, TimeUnit.MILLISECONDS); bisInspAllRlationPers.setMobilenumb(UserMsgSectrityUtils.blurPhone(bisInspAllRlationPers.getMobilenumb())); //插入用户登录记录表 insertLoginInfo(loginDto.getPhone(), Constants.LOGIN_SUCCESS, "user.login.success"); return buildSuccessResponse(bisInspAllRlationPers, uuid); } public void insertLoginInfo(String username, String status, String message) { final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); final String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); String address = ""; StringBuilder s = new StringBuilder(); s.append(LogUtils.getBlock(ip)); s.append(address); s.append(LogUtils.getBlock(username)); s.append(LogUtils.getBlock(status)); s.append(LogUtils.getBlock(message)); // 获取客户端操作系统 String os = userAgent.getOperatingSystem().getName(); // 获取客户端浏览器 String browser = userAgent.getBrowser().getName(); // 封装对象 BisInspLoginInfo bisInspLoginInfo = new BisInspLoginInfo(); bisInspLoginInfo.setUserName(username); bisInspLoginInfo.setIp(ip); bisInspLoginInfo.setLoginLocation(address); bisInspLoginInfo.setBrowser(browser); bisInspLoginInfo.setOs(os); bisInspLoginInfo.setMsg(message); bisInspLoginInfo.setStatus(Constants.SUCCESS); bisInspLoginInfo.setLoginTime(new Date()); // 插入数据 bisInspLoginInfoService.insert(bisInspLoginInfo); } @Override public BaseResponse loginByPwd(LoginDto loginDto, HttpServletRequest request) { long startTime = System.currentTimeMillis(); //代码执行结束时间 long endTime = System.currentTimeMillis(); logger.info("----------------login startTime" + startTime + "----------------------------------------"); String uuidCode = ""; Object object = this.redisTemplate.opsForValue().get(loginDto.getImgCodeId()); if (object != null) { redisTemplate.delete(loginDto.getImgCodeId()); uuidCode = object.toString(); } if (StringUtils.isBlank(loginDto.getImgCode()) || StringUtils.isBlank(loginDto.getPhone()) || StringUtils.isBlank(loginDto.getImgCodeId())) { return buildFailResponse(1512, "缺少参数"); } //密码登录错误大于5次则拉黑IP,禁止登录 String ip = IPUtils.getIpAddr(request); String blackListPwd = "blackListPwd:" + loginDto.getPhone() + ":" + ip; Integer blackPwdSize = redisTemplate.opsForValue().get(blackListPwd) == null ? 0 : (int) redisTemplate.opsForValue().get(blackListPwd); if (blackPwdSize > 5) { return buildFailResponse(9991, "密码错误次数超过5次,ip锁定两个小时!"); } String inputCode = Base64Util.encodeStr(loginDto.getImgCode().toLowerCase()); if (!(uuidCode.equalsIgnoreCase(inputCode))) { return buildFailResponse(1500, "您输入的验证码不正确或已过期,请点击验证码图片刷新,重新输入!"); } BisInspAllRlationPers p = bisInspAllRlationPersService.getBy(Builder.of(BisInspAllRlationPersParam::new) .with(BisInspAllRlationPersParam::setMobilenumb, loginDto.getPhone()) .build()); if (p == null) { return buildFailResponse(1002, "该手机号尚未注册", "", ""); } if (StringUtils.isBlank(p.getPwd())) { return buildFailResponse(1511, "密码不能为空", "", ""); } if (!p.getPwd().equals(MD5.getMD5(aesUtil.desEncrypt(loginDto.getPwd())))) { //密码错误次数加1an loginFailurePwd(loginDto.getPhone(), ip); return buildFailResponse(1510, "您输入的密码错误,请核对后输入!"); } //如果是广东用户手机登录提示停用 logger.info("login--------------------------------------p.getProvince():" + p.getProvince() + "--------------------------------------------------------"); if (p.getProvince().equals("440000000000")) { return buildFailResponse(1002, "广东暂停使用", "", ""); } //省级平台禁用四川用户登录,启用本地平台 if (!scLoginEnabled) { if (p.getProvince().substring(0, 2).equals("51")) { return buildFailResponse(10015, "四川省用户停用此平台,请访问本地部署平台。系统地址:http://101.207.130.194:37210", "", ""); } } //当前时间减-上次修改密码时间 endTime = System.currentTimeMillis(); if(null!=p.getLoginTm()) { long daysBetween = (endTime - p.getLoginTm().getTime()) / 24 / 60 / 60 / 1000; if (daysBetween > 30) { //超30天未修改密码 return buildFailResponse(1900, "超30天未修改密码请修改,请短信登录后修改密码!"); } } logger.info("-----------------------setPwd :" + (endTime - startTime) + "-------------------------------------------"); p.setPwd(null); p = getBisInspAllRlations(p); BisInspAllRlationPers pers = new BisInspAllRlationPers(); pers.setGuid(p.getGuid()); pers.setLoginTm(new Date()); if (StringUtils.isBlank(p.getPersType())) { p.setPersType("3"); pers.setPersType("3"); } bisInspAllRlationPersService.update(pers); endTime = System.currentTimeMillis(); logger.info("-----------------------update : " + (endTime - startTime) + "-------------------------------------------"); String uuid = UuidUtil.uuid(); //bisInspAllRlationPersService.sendChannel(uuid, p, request, PlusEnum.ADD.getNumber()); String accessToken = JWTTokenUtil.sign(bisInspAllRlationPersService.getLoginUser(p), p.getGuid()); redisTemplate.opsForValue().set(uuid, accessToken, JWTTokenUtil.maxAge, TimeUnit.MILLISECONDS); redisTemplate.opsForValue().set(uuid + p.getGuid(), accessToken, JWTTokenUtil.refreshmaxAge, TimeUnit.MILLISECONDS); p.setMobilenumb(UserMsgSectrityUtils.blurPhone(p.getMobilenumb())); //插入用户登录记录表 insertLoginInfo(loginDto.getPhone(), Constants.LOGIN_SUCCESS, "user.login.success"); endTime = System.currentTimeMillis(); logger.info("-----------------------end : " + (endTime - startTime) + "-------------------------------------------"); return buildSuccessResponse(p, uuid); } @Override public BaseResponse updatePwdMd5() { //获取所有用户,并更新密码为MD5加密后的 List bisInspAllRlationPers = bisInspAllRlationPersService.findList(Builder.of(BisInspAllRlationPersParam::new).build()); for (BisInspAllRlationPers bisInspAllRlationPer : bisInspAllRlationPers ) { //密码为空则设置20个数字的密码 if (StringUtils.isBlank(bisInspAllRlationPer.getPwd())) { //获取随机数包含数字和字符 String roundmString = VerifyCodeUtils.generateVerifyCode(20); bisInspAllRlationPer.setPwd(MD5.getMD5(roundmString)); } else { //密码不为空则判断是否跟手机号一致,如果一致改为 20位随机数 if (MD5.getMD5(bisInspAllRlationPer.getMobilenumb()).equals(bisInspAllRlationPer.getPwd())) { String roundmString = VerifyCodeUtils.generateVerifyCode(20); bisInspAllRlationPer.setPwd(MD5.getMD5(roundmString)); } } bisInspAllRlationPer.setLoginTm(new Date()); bisInspAllRlationPersService.update(bisInspAllRlationPer); } return buildFailResponse("密码MD5更新成功"); } private BisInspAllRlationPers getBisInspAllRlations(BisInspAllRlationPers bisInspAllRlationPers) { // 1.设置默认显示机构和所能看到的所有机构 BisInspOrg bisInspOrg = new BisInspOrg(); if (StringUtils.isNotBlank(bisInspAllRlationPers.getOrgId())) { // 设置所有能看到的机构 BisInspOrgParam inspOrgParam = new BisInspOrgParam(); inspOrgParam.setPersId(bisInspAllRlationPers.getGuid()); List inspOrgList = bisInspOrgDao.findPersOrgList(inspOrgParam); inspOrgList.forEach(o -> o.setRlcode(o.getAdCode())); bisInspAllRlationPers.setAllOrg(inspOrgList); String orgId = bisInspAllRlationPers.getOrgId(); // 获取所有orgId 判断用户所属机构是否在其中,没有 选择第一个机构 为默认机构 if (inspOrgList != null && inspOrgList.size() > 0) { orgId = inspOrgList.get(0).getOrgId(); for (BisInspOrg org : inspOrgList) { if (org.getOrgId().equals(bisInspAllRlationPers.getOrgId())) { orgId = bisInspAllRlationPers.getOrgId(); break; } } } bisInspOrg = olBisInspOrgService.getDefaultOrg(orgId); bisInspAllRlationPers.setDefaultOrg(bisInspOrg); } if (StringUtils.isNotBlank(bisInspAllRlationPers.getGuid())) { List allNode = organizationTree.getAllNode(bisInspAllRlationPers.getGuid(), "", bisInspAllRlationPers.getOrgId(), "", "", "", "", ""); if (allNode.size() > 0) { StringBuffer s = new StringBuffer(); s.append("1"); String sk = "0"; String ry = "000"; String sh = "0"; String ogc = "0"; String dxs = "0"; String sz = "0"; String sd = "0"; for (BisInspAll b : allNode) { if ("001".equals(b.getId().substring(0, 3))) { sk = "1"; } if ("002".equals(b.getId().substring(0, 3))) { ry = "111"; } if ("003".equals(b.getId().substring(0, 3))) { sh = "1"; } if ("004".equals(b.getId().substring(0, 3))) { ogc = "1"; } if ("005".equals(b.getId().substring(0, 3))) { dxs = "1"; } if ("006".equals(b.getId().substring(0, 3))) { sz = "1"; } if ("011".equals(b.getId().substring(0, 3))) { sd = "1"; } } s.append(sk).append(ry).append(sh).append(ogc).append(dxs).append(sz).append(sd); bisInspAllRlationPers.setJurisdiction(s.toString()); } else { bisInspAllRlationPers.setJurisdiction("100000000"); } bisInspAllRlationPers.setAllNode(allNode); } return bisInspAllRlationPers; } /** * 登陆失败处理: * 一定时间内,登陆失败超过5次,禁止登录1小时 * * @return */ private BaseResponse loginFailureDual(String phone, String ip) { String blackListKey = "blackList:" + phone + ":" + ip; String loginTimeKey = phone + "_time:" + ip; String loginCountKey = phone + "_login_count:" + ip; long startTime = redisTemplate.opsForValue().get(loginTimeKey) == null ? 0L : (long) redisTemplate.opsForValue().get(loginTimeKey); if (startTime == 0L) { redisTemplate.opsForValue().set(loginTimeKey, System.currentTimeMillis()); redisTemplate.opsForValue().set(loginCountKey, 1); } else { int count = redisTemplate.opsForValue().get(loginCountKey) == null ? 0 : (int) redisTemplate.opsForValue().get(loginCountKey); if (count < 5) { count = count + 1; redisTemplate.opsForValue().set(loginCountKey, count); } else { long time = (System.currentTimeMillis() - startTime) / 3600000L; if (time > 1) { redisTemplate.opsForValue().set(loginCountKey, 0); redisTemplate.opsForValue().set(loginTimeKey, 0L); } else { redisTemplate.opsForValue().set(blackListKey, phone, 3600000L, TimeUnit.MILLISECONDS); return buildFailResponse(9991, "检测到该手机号登录过于频繁,可能存在恶意操作,系统已将手机用户暂时列入黑名单,请1小时后再试!"); } } } return buildFailResponse(1001, "验证码错误", "", ""); } /** * 登陆失败处理: * 一定时间内,登陆失败超过5次,禁止登录2小时 * * @return */ private void loginFailurePwd(String phone, String ip) { String blackListPwd = "blackListPwd:" + phone + ":" + ip; Integer blackListPwdSize = redisTemplate.opsForValue().get(blackListPwd) == null ? 0 : (int) redisTemplate.opsForValue().get(blackListPwd); blackListPwdSize = blackListPwdSize + 1; redisTemplate.opsForValue().set(blackListPwd, blackListPwdSize, 3600000L, TimeUnit.MILLISECONDS); } public static void main(String[] args) throws Exception { System.out.println("510000000000".substring(0, 2)); } }