e705b799e0f6c1f44a35e46fea7d7e49859da347.svn-base 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. package cn.com.goldenwater.dcproj.service.impl.login;
  2. import cn.com.goldenwater.core.web.BaseResponse;
  3. import cn.com.goldenwater.dcproj.constValue.Constants;
  4. import cn.com.goldenwater.dcproj.dao.BisInspOrgDao;
  5. import cn.com.goldenwater.dcproj.dao.GwStaticUserDao;
  6. import cn.com.goldenwater.dcproj.dto.LoginDto;
  7. import cn.com.goldenwater.dcproj.model.BisInspAll;
  8. import cn.com.goldenwater.dcproj.model.BisInspAllRlationPers;
  9. import cn.com.goldenwater.dcproj.model.BisInspLoginInfo;
  10. import cn.com.goldenwater.dcproj.model.BisInspOrg;
  11. import cn.com.goldenwater.dcproj.model.GwStaticUser;
  12. import cn.com.goldenwater.dcproj.param.BisInspAllRlationPersParam;
  13. import cn.com.goldenwater.dcproj.param.BisInspOrgParam;
  14. import cn.com.goldenwater.dcproj.service.BisInspAllRlationPersService;
  15. import cn.com.goldenwater.dcproj.service.BisInspLoginInfoService;
  16. import cn.com.goldenwater.dcproj.service.LoginService;
  17. import cn.com.goldenwater.dcproj.service.OlBisInspOrgService;
  18. import cn.com.goldenwater.dcproj.service.impl.system.OrganizationTreeImpl;
  19. import cn.com.goldenwater.dcproj.util.Base64Util;
  20. import cn.com.goldenwater.dcproj.utils.Builder;
  21. import cn.com.goldenwater.dcproj.utils.IpUtils;
  22. import cn.com.goldenwater.dcproj.utils.JWTTokenUtil;
  23. import cn.com.goldenwater.dcproj.utils.LogUtils;
  24. import cn.com.goldenwater.dcproj.utils.MD5;
  25. import cn.com.goldenwater.dcproj.utils.ServletUtils;
  26. import cn.com.goldenwater.dcproj.utils.UserMsgSectrityUtils;
  27. import cn.com.goldenwater.dcproj.utils.VerifyCodeUtils;
  28. import cn.com.goldenwater.dcproj.utils.aesUtil;
  29. import cn.com.goldenwater.id.util.UuidUtil;
  30. import cn.com.goldenwater.util.common.IPUtils;
  31. import eu.bitwalker.useragentutils.UserAgent;
  32. import org.apache.commons.lang3.StringUtils;
  33. import org.slf4j.Logger;
  34. import org.slf4j.LoggerFactory;
  35. import org.springframework.beans.factory.annotation.Autowired;
  36. import org.springframework.beans.factory.annotation.Value;
  37. import org.springframework.data.redis.core.RedisTemplate;
  38. import org.springframework.stereotype.Service;
  39. import javax.servlet.http.HttpServletRequest;
  40. import java.time.temporal.ChronoUnit;
  41. import java.util.Date;
  42. import java.util.List;
  43. import java.util.concurrent.TimeUnit;
  44. import static cn.com.goldenwater.core.web.BaseController.buildFailResponse;
  45. import static cn.com.goldenwater.core.web.BaseController.buildSuccessResponse;
  46. /**
  47. * @author: LinQiLong
  48. * @create: 2021/10/27 11:27
  49. */
  50. @Service
  51. public class LoginServiceImpl implements LoginService {
  52. private Logger logger = LoggerFactory.getLogger(getClass());
  53. @Value("${intercept.enable}")
  54. public Boolean enterceptEnable;
  55. @Value("${smsCode}")
  56. private String smsCode;
  57. @Autowired
  58. private BisInspAllRlationPersService bisInspAllRlationPersService;
  59. @Autowired
  60. private RedisTemplate redisTemplate;
  61. @Autowired
  62. private GwStaticUserDao gwStaticUserDao;
  63. @Autowired
  64. private OrganizationTreeImpl organizationTree;
  65. @Autowired
  66. private BisInspOrgDao bisInspOrgDao;
  67. @Autowired
  68. private OlBisInspOrgService olBisInspOrgService;
  69. @Value("${sc.login.enabled:true}")
  70. private Boolean scLoginEnabled;
  71. @Autowired
  72. private BisInspLoginInfoService bisInspLoginInfoService;
  73. @Override
  74. public BaseResponse login(LoginDto loginDto, HttpServletRequest request) {
  75. String ip = IPUtils.getIpAddr(request);
  76. String blackListKey = "blackList:" + loginDto.getPhone() + ":" + ip;
  77. String blackIp = (String) redisTemplate.opsForValue().get(blackListKey);
  78. if (loginDto.getPhone().equals(blackIp)) {
  79. return buildFailResponse(9991, "检测到该手机号登录过于频繁,可能存在恶意操作,系统已将手机用户暂时列入黑名单,请1小时后再试!");
  80. }
  81. // String origin = request.getHeader("Origin");
  82. // String referer = request.getHeader("Referer");
  83. // if (!referer.startsWith(origin)) {
  84. // return buildFailResponse(1005,"请求网址不同");
  85. // }
  86. if (loginDto.getCode().length() != 6) {
  87. return buildFailResponse("验证码有误!");
  88. }
  89. BisInspAllRlationPers p = bisInspAllRlationPersService.getBy(Builder.of(BisInspAllRlationPersParam::new)
  90. .with(BisInspAllRlationPersParam::setMobilenumb, loginDto.getPhone())
  91. .build());
  92. if (p == null) {
  93. return buildFailResponse(1002, "该手机号尚未注册", "", "");
  94. }
  95. //如果是广东用户手机登录提示停用
  96. logger.info("login--------------------------------------p.getProvince():" + p.getProvince() + "--------------------------------------------------------");
  97. if (p.getProvince().equals("440000000000")) {
  98. return buildFailResponse(1002, "广东暂停使用", "", "");
  99. }
  100. //省级平台禁用四川用户登录,启用本地平台
  101. if (!scLoginEnabled) {
  102. if (p.getProvince().substring(0, 2).equals("51")) {
  103. return buildFailResponse(10015, "四川省用户停用此平台,请访问本地部署平台。系统地址:http://101.207.130.194:37210", "", "");
  104. }
  105. }
  106. // 根据phone-code获取用户信息
  107. BisInspAllRlationPers bisInspAllRlationPers = bisInspAllRlationPersService.loginByCode(loginDto.getPhone(), loginDto.getCode());
  108. boolean logincode = true;
  109. if (bisInspAllRlationPers == null) {
  110. GwStaticUser gwStaticUser = gwStaticUserDao.get(loginDto.getPhone());
  111. if (gwStaticUser != null) {
  112. // 判断是否与固定验证码相同,相同时获取用户信息
  113. if (smsCode.equals(loginDto.getCode())) {
  114. bisInspAllRlationPers = bisInspAllRlationPersService.getBy(Builder.of(BisInspAllRlationPersParam::new)
  115. .with(BisInspAllRlationPersParam::setMobilenumb, loginDto.getPhone())
  116. .build());
  117. logincode = false;
  118. }
  119. }
  120. }
  121. //发送信息成功后记录数据
  122. if (logincode) {
  123. String yzm = (String) redisTemplate.opsForValue().get(loginDto.getPhone());
  124. if (StringUtils.isBlank(yzm)) {
  125. return buildFailResponse("图片验证码已经过期,请重新验证!!");
  126. }
  127. String[] arrays = yzm.split("_");
  128. //验证码为arrays[0]
  129. String yzmReal = (String) redisTemplate.opsForValue().get(arrays[1]);
  130. if (StringUtils.isBlank(yzm) || "null".equals(yzm) || yzmReal == null || !yzmReal.equals(arrays[0])) {
  131. return buildFailResponse("图片验证码已经过期,请重新输入!!");
  132. }
  133. }
  134. if (bisInspAllRlationPers == null) {
  135. return loginFailureDual(loginDto.getPhone(), ip);
  136. }
  137. bisInspAllRlationPers.setPwd(null);
  138. bisInspAllRlationPers = getBisInspAllRlations(bisInspAllRlationPers);
  139. BisInspAllRlationPers pers = new BisInspAllRlationPers();
  140. pers.setGuid(bisInspAllRlationPers.getGuid());
  141. pers.setLoginTm(new Date());
  142. if (StringUtils.isBlank(bisInspAllRlationPers.getPersType())) {
  143. bisInspAllRlationPers.setPersType("3");
  144. pers.setPersType("3");
  145. }
  146. bisInspAllRlationPersService.update(pers);
  147. String uuid = UuidUtil.uuid();
  148. //bisInspAllRlationPersService.sendChannel(uuid, bisInspAllRlationPers, request, PlusEnum.ADD.getNumber());
  149. String accessToken = JWTTokenUtil.sign(bisInspAllRlationPersService.getLoginUser(bisInspAllRlationPers), bisInspAllRlationPers.getGuid());
  150. redisTemplate.opsForValue().set(uuid, accessToken, JWTTokenUtil.maxAge, TimeUnit.MILLISECONDS);
  151. redisTemplate.opsForValue().set(uuid + bisInspAllRlationPers.getGuid(), accessToken, JWTTokenUtil.refreshmaxAge, TimeUnit.MILLISECONDS);
  152. bisInspAllRlationPers.setMobilenumb(UserMsgSectrityUtils.blurPhone(bisInspAllRlationPers.getMobilenumb()));
  153. //插入用户登录记录表
  154. insertLoginInfo(loginDto.getPhone(), Constants.LOGIN_SUCCESS, "user.login.success");
  155. return buildSuccessResponse(bisInspAllRlationPers, uuid);
  156. }
  157. public void insertLoginInfo(String username, String status, String message) {
  158. final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
  159. final String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
  160. String address = "";
  161. StringBuilder s = new StringBuilder();
  162. s.append(LogUtils.getBlock(ip));
  163. s.append(address);
  164. s.append(LogUtils.getBlock(username));
  165. s.append(LogUtils.getBlock(status));
  166. s.append(LogUtils.getBlock(message));
  167. // 获取客户端操作系统
  168. String os = userAgent.getOperatingSystem().getName();
  169. // 获取客户端浏览器
  170. String browser = userAgent.getBrowser().getName();
  171. // 封装对象
  172. BisInspLoginInfo bisInspLoginInfo = new BisInspLoginInfo();
  173. bisInspLoginInfo.setUserName(username);
  174. bisInspLoginInfo.setIp(ip);
  175. bisInspLoginInfo.setLoginLocation(address);
  176. bisInspLoginInfo.setBrowser(browser);
  177. bisInspLoginInfo.setOs(os);
  178. bisInspLoginInfo.setMsg(message);
  179. bisInspLoginInfo.setStatus(Constants.SUCCESS);
  180. bisInspLoginInfo.setLoginTime(new Date());
  181. // 插入数据
  182. bisInspLoginInfoService.insert(bisInspLoginInfo);
  183. }
  184. @Override
  185. public BaseResponse loginByPwd(LoginDto loginDto, HttpServletRequest request) {
  186. long startTime = System.currentTimeMillis();
  187. //代码执行结束时间
  188. long endTime = System.currentTimeMillis();
  189. logger.info("----------------login startTime" + startTime + "----------------------------------------");
  190. String uuidCode = "";
  191. Object object = this.redisTemplate.opsForValue().get(loginDto.getImgCodeId());
  192. if (object != null) {
  193. redisTemplate.delete(loginDto.getImgCodeId());
  194. uuidCode = object.toString();
  195. }
  196. if (StringUtils.isBlank(loginDto.getImgCode()) || StringUtils.isBlank(loginDto.getPhone()) || StringUtils.isBlank(loginDto.getImgCodeId())) {
  197. return buildFailResponse(1512, "缺少参数");
  198. }
  199. //密码登录错误大于5次则拉黑IP,禁止登录
  200. String ip = IPUtils.getIpAddr(request);
  201. String blackListPwd = "blackListPwd:" + loginDto.getPhone() + ":" + ip;
  202. Integer blackPwdSize = redisTemplate.opsForValue().get(blackListPwd) == null ? 0 : (int) redisTemplate.opsForValue().get(blackListPwd);
  203. if (blackPwdSize > 5) {
  204. return buildFailResponse(9991, "密码错误次数超过5次,ip锁定两个小时!");
  205. }
  206. String inputCode = Base64Util.encodeStr(loginDto.getImgCode().toLowerCase());
  207. if (!(uuidCode.equalsIgnoreCase(inputCode))) {
  208. return buildFailResponse(1500, "您输入的验证码不正确或已过期,请点击验证码图片刷新,重新输入!");
  209. }
  210. BisInspAllRlationPers p = bisInspAllRlationPersService.getBy(Builder.of(BisInspAllRlationPersParam::new)
  211. .with(BisInspAllRlationPersParam::setMobilenumb, loginDto.getPhone())
  212. .build());
  213. if (p == null) {
  214. return buildFailResponse(1002, "该手机号尚未注册", "", "");
  215. }
  216. if (StringUtils.isBlank(p.getPwd())) {
  217. return buildFailResponse(1511, "密码不能为空", "", "");
  218. }
  219. if (!p.getPwd().equals(MD5.getMD5(aesUtil.desEncrypt(loginDto.getPwd())))) {
  220. //密码错误次数加1an
  221. loginFailurePwd(loginDto.getPhone(), ip);
  222. return buildFailResponse(1510, "您输入的密码错误,请核对后输入!");
  223. }
  224. //如果是广东用户手机登录提示停用
  225. logger.info("login--------------------------------------p.getProvince():" + p.getProvince() + "--------------------------------------------------------");
  226. if (p.getProvince().equals("440000000000")) {
  227. return buildFailResponse(1002, "广东暂停使用", "", "");
  228. }
  229. //省级平台禁用四川用户登录,启用本地平台
  230. if (!scLoginEnabled) {
  231. if (p.getProvince().substring(0, 2).equals("51")) {
  232. return buildFailResponse(10015, "四川省用户停用此平台,请访问本地部署平台。系统地址:http://101.207.130.194:37210", "", "");
  233. }
  234. }
  235. //当前时间减-上次修改密码时间
  236. endTime = System.currentTimeMillis();
  237. if(null!=p.getLoginTm()) {
  238. long daysBetween = (endTime - p.getLoginTm().getTime()) / 24 / 60 / 60 / 1000;
  239. if (daysBetween > 30) {
  240. //超30天未修改密码
  241. return buildFailResponse(1900, "超30天未修改密码请修改,请短信登录后修改密码!");
  242. }
  243. }
  244. logger.info("-----------------------setPwd :" + (endTime - startTime) + "-------------------------------------------");
  245. p.setPwd(null);
  246. p = getBisInspAllRlations(p);
  247. BisInspAllRlationPers pers = new BisInspAllRlationPers();
  248. pers.setGuid(p.getGuid());
  249. pers.setLoginTm(new Date());
  250. if (StringUtils.isBlank(p.getPersType())) {
  251. p.setPersType("3");
  252. pers.setPersType("3");
  253. }
  254. bisInspAllRlationPersService.update(pers);
  255. endTime = System.currentTimeMillis();
  256. logger.info("-----------------------update : " + (endTime - startTime) + "-------------------------------------------");
  257. String uuid = UuidUtil.uuid();
  258. //bisInspAllRlationPersService.sendChannel(uuid, p, request, PlusEnum.ADD.getNumber());
  259. String accessToken = JWTTokenUtil.sign(bisInspAllRlationPersService.getLoginUser(p), p.getGuid());
  260. redisTemplate.opsForValue().set(uuid, accessToken, JWTTokenUtil.maxAge, TimeUnit.MILLISECONDS);
  261. redisTemplate.opsForValue().set(uuid + p.getGuid(), accessToken, JWTTokenUtil.refreshmaxAge, TimeUnit.MILLISECONDS);
  262. p.setMobilenumb(UserMsgSectrityUtils.blurPhone(p.getMobilenumb()));
  263. //插入用户登录记录表
  264. insertLoginInfo(loginDto.getPhone(), Constants.LOGIN_SUCCESS, "user.login.success");
  265. endTime = System.currentTimeMillis();
  266. logger.info("-----------------------end : " + (endTime - startTime) + "-------------------------------------------");
  267. return buildSuccessResponse(p, uuid);
  268. }
  269. @Override
  270. public BaseResponse updatePwdMd5() {
  271. //获取所有用户,并更新密码为MD5加密后的
  272. List<BisInspAllRlationPers> bisInspAllRlationPers = bisInspAllRlationPersService.findList(Builder.of(BisInspAllRlationPersParam::new).build());
  273. for (BisInspAllRlationPers bisInspAllRlationPer : bisInspAllRlationPers
  274. ) {
  275. //密码为空则设置20个数字的密码
  276. if (StringUtils.isBlank(bisInspAllRlationPer.getPwd())) {
  277. //获取随机数包含数字和字符
  278. String roundmString = VerifyCodeUtils.generateVerifyCode(20);
  279. bisInspAllRlationPer.setPwd(MD5.getMD5(roundmString));
  280. } else {
  281. //密码不为空则判断是否跟手机号一致,如果一致改为 20位随机数
  282. if (MD5.getMD5(bisInspAllRlationPer.getMobilenumb()).equals(bisInspAllRlationPer.getPwd())) {
  283. String roundmString = VerifyCodeUtils.generateVerifyCode(20);
  284. bisInspAllRlationPer.setPwd(MD5.getMD5(roundmString));
  285. }
  286. }
  287. bisInspAllRlationPer.setLoginTm(new Date());
  288. bisInspAllRlationPersService.update(bisInspAllRlationPer);
  289. }
  290. return buildFailResponse("密码MD5更新成功");
  291. }
  292. private BisInspAllRlationPers getBisInspAllRlations(BisInspAllRlationPers bisInspAllRlationPers) {
  293. // 1.设置默认显示机构和所能看到的所有机构
  294. BisInspOrg bisInspOrg = new BisInspOrg();
  295. if (StringUtils.isNotBlank(bisInspAllRlationPers.getOrgId())) {
  296. // 设置所有能看到的机构
  297. BisInspOrgParam inspOrgParam = new BisInspOrgParam();
  298. inspOrgParam.setPersId(bisInspAllRlationPers.getGuid());
  299. List<BisInspOrg> inspOrgList = bisInspOrgDao.findPersOrgList(inspOrgParam);
  300. inspOrgList.forEach(o -> o.setRlcode(o.getAdCode()));
  301. bisInspAllRlationPers.setAllOrg(inspOrgList);
  302. String orgId = bisInspAllRlationPers.getOrgId();
  303. // 获取所有orgId 判断用户所属机构是否在其中,没有 选择第一个机构 为默认机构
  304. if (inspOrgList != null && inspOrgList.size() > 0) {
  305. orgId = inspOrgList.get(0).getOrgId();
  306. for (BisInspOrg org : inspOrgList) {
  307. if (org.getOrgId().equals(bisInspAllRlationPers.getOrgId())) {
  308. orgId = bisInspAllRlationPers.getOrgId();
  309. break;
  310. }
  311. }
  312. }
  313. bisInspOrg = olBisInspOrgService.getDefaultOrg(orgId);
  314. bisInspAllRlationPers.setDefaultOrg(bisInspOrg);
  315. }
  316. if (StringUtils.isNotBlank(bisInspAllRlationPers.getGuid())) {
  317. List<BisInspAll> allNode = organizationTree.getAllNode(bisInspAllRlationPers.getGuid(), "", bisInspAllRlationPers.getOrgId(), "", "", "", "", "");
  318. if (allNode.size() > 0) {
  319. StringBuffer s = new StringBuffer();
  320. s.append("1");
  321. String sk = "0";
  322. String ry = "000";
  323. String sh = "0";
  324. String ogc = "0";
  325. String dxs = "0";
  326. String sz = "0";
  327. String sd = "0";
  328. for (BisInspAll b : allNode) {
  329. if ("001".equals(b.getId().substring(0, 3))) {
  330. sk = "1";
  331. }
  332. if ("002".equals(b.getId().substring(0, 3))) {
  333. ry = "111";
  334. }
  335. if ("003".equals(b.getId().substring(0, 3))) {
  336. sh = "1";
  337. }
  338. if ("004".equals(b.getId().substring(0, 3))) {
  339. ogc = "1";
  340. }
  341. if ("005".equals(b.getId().substring(0, 3))) {
  342. dxs = "1";
  343. }
  344. if ("006".equals(b.getId().substring(0, 3))) {
  345. sz = "1";
  346. }
  347. if ("011".equals(b.getId().substring(0, 3))) {
  348. sd = "1";
  349. }
  350. }
  351. s.append(sk).append(ry).append(sh).append(ogc).append(dxs).append(sz).append(sd);
  352. bisInspAllRlationPers.setJurisdiction(s.toString());
  353. } else {
  354. bisInspAllRlationPers.setJurisdiction("100000000");
  355. }
  356. bisInspAllRlationPers.setAllNode(allNode);
  357. }
  358. return bisInspAllRlationPers;
  359. }
  360. /**
  361. * 登陆失败处理:
  362. * 一定时间内,登陆失败超过5次,禁止登录1小时
  363. *
  364. * @return
  365. */
  366. private BaseResponse loginFailureDual(String phone, String ip) {
  367. String blackListKey = "blackList:" + phone + ":" + ip;
  368. String loginTimeKey = phone + "_time:" + ip;
  369. String loginCountKey = phone + "_login_count:" + ip;
  370. long startTime = redisTemplate.opsForValue().get(loginTimeKey) == null ? 0L : (long) redisTemplate.opsForValue().get(loginTimeKey);
  371. if (startTime == 0L) {
  372. redisTemplate.opsForValue().set(loginTimeKey, System.currentTimeMillis());
  373. redisTemplate.opsForValue().set(loginCountKey, 1);
  374. } else {
  375. int count = redisTemplate.opsForValue().get(loginCountKey) == null ? 0 : (int) redisTemplate.opsForValue().get(loginCountKey);
  376. if (count < 5) {
  377. count = count + 1;
  378. redisTemplate.opsForValue().set(loginCountKey, count);
  379. } else {
  380. long time = (System.currentTimeMillis() - startTime) / 3600000L;
  381. if (time > 1) {
  382. redisTemplate.opsForValue().set(loginCountKey, 0);
  383. redisTemplate.opsForValue().set(loginTimeKey, 0L);
  384. } else {
  385. redisTemplate.opsForValue().set(blackListKey, phone, 3600000L, TimeUnit.MILLISECONDS);
  386. return buildFailResponse(9991, "检测到该手机号登录过于频繁,可能存在恶意操作,系统已将手机用户暂时列入黑名单,请1小时后再试!");
  387. }
  388. }
  389. }
  390. return buildFailResponse(1001, "验证码错误", "", "");
  391. }
  392. /**
  393. * 登陆失败处理:
  394. * 一定时间内,登陆失败超过5次,禁止登录2小时
  395. *
  396. * @return
  397. */
  398. private void loginFailurePwd(String phone, String ip) {
  399. String blackListPwd = "blackListPwd:" + phone + ":" + ip;
  400. Integer blackListPwdSize = redisTemplate.opsForValue().get(blackListPwd) == null ? 0 : (int) redisTemplate.opsForValue().get(blackListPwd);
  401. blackListPwdSize = blackListPwdSize + 1;
  402. redisTemplate.opsForValue().set(blackListPwd, blackListPwdSize, 3600000L, TimeUnit.MILLISECONDS);
  403. }
  404. public static void main(String[] args) throws Exception {
  405. System.out.println("510000000000".substring(0, 2));
  406. }
  407. }