UserServiceImpl.java 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. package com.uas.sso.service.impl;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.uas.sso.common.encrypt.MD5;
  5. import com.uas.sso.common.util.HttpUtil;
  6. import com.uas.sso.core.Const;
  7. import com.uas.sso.core.ICallable;
  8. import com.uas.sso.core.Status;
  9. import com.uas.sso.core.Type;
  10. import com.uas.sso.dao.UserDao;
  11. import com.uas.sso.dao.UserRecordDao;
  12. import com.uas.sso.entity.*;
  13. import com.uas.sso.exception.VisibleError;
  14. import com.uas.sso.logging.LoggerManager;
  15. import com.uas.sso.logging.SyncBufferedLogger;
  16. import com.uas.sso.logging.UserBufferedLogger;
  17. import com.uas.sso.service.*;
  18. import com.uas.sso.util.AccountTypeUtils;
  19. import com.uas.sso.util.ExecuteUtils;
  20. import org.springframework.beans.factory.annotation.Autowired;
  21. import org.springframework.data.domain.Page;
  22. import org.springframework.data.domain.PageRequest;
  23. import org.springframework.data.domain.Pageable;
  24. import org.springframework.data.jpa.domain.Specification;
  25. import org.springframework.stereotype.Service;
  26. import org.springframework.ui.ModelMap;
  27. import org.springframework.util.CollectionUtils;
  28. import org.springframework.util.StringUtils;
  29. import com.uas.sso.exception.AccountException;
  30. import javax.persistence.criteria.*;
  31. import java.sql.Timestamp;
  32. import java.util.ArrayList;
  33. import java.util.Iterator;
  34. import java.util.List;
  35. import java.util.Set;
  36. /**
  37. * 用户service实现类
  38. *
  39. * @author wangmh
  40. * @date 2018/1/2
  41. */
  42. @Service
  43. public class UserServiceImpl implements UserService {
  44. @Autowired
  45. private UserDao userDao;
  46. @Autowired
  47. private UserRecordDao userRecordDao;
  48. @Autowired
  49. private UserValidService userValidService;
  50. @Autowired
  51. private UserspaceService userspaceService;
  52. @Autowired
  53. private AppService appService;
  54. @Autowired
  55. private UserQuestionService userQuestionService;
  56. private UserBufferedLogger userLog = LoggerManager.getLogger(UserBufferedLogger.class);
  57. private SyncBufferedLogger syncLog = LoggerManager.getLogger(SyncBufferedLogger.class);
  58. @Override
  59. public User findByMobile(String mobile, String mobileArea) {
  60. return userDao.findByMobileAndMobileArea(mobile, mobileArea);
  61. }
  62. @Override
  63. public User findByMobile(String mobile) {
  64. return userDao.findByMobile(mobile);
  65. }
  66. @Override
  67. public boolean mobileHasRegistered(String mobile) {
  68. User user = userDao.findByMobile(mobile);
  69. if (user == null) {
  70. return false;
  71. }
  72. return true;
  73. }
  74. @Override
  75. public boolean emailHasRegistered(String email) {
  76. List<User> users = userDao.findByEmail(email);
  77. if (CollectionUtils.isEmpty(users)) {
  78. return false;
  79. }
  80. return true;
  81. }
  82. @Override
  83. public synchronized User register(User user) {
  84. String noEncryPwd = user.getPassword();
  85. // 校验手机号是否被注册
  86. if (mobileHasRegistered(user.getMobile())) {
  87. throw new VisibleError("该手机号已被注册");
  88. }
  89. // 由于现在不考虑手机号所属区域,默认为中国大陆
  90. if (StringUtils.isEmpty(user.getMobileArea())) {
  91. user.setMobileArea(Const.CONTINENT);
  92. }
  93. // 设置基本属性,手机号默认已认证
  94. user.setRegisterDate(new Timestamp(System.currentTimeMillis()));
  95. Long uu = userDao.findMaxUU();
  96. user.setUserUU(uu == null ? 10000 : (uu + 1));
  97. user.setSalt(String.valueOf(user.getUserUU()));
  98. user.setMobileValidCode((short) Status.AUTHENTICATED.getCode());
  99. user.setEmailValidCode((short) Status.NOT_APPLYING.getCode());
  100. user.setIdentityValidCode((short) Status.NOT_APPLYING.getCode());
  101. user.setPassword(getEncryPassword(Const.ENCRY_FORMAT, user.getPassword(), user.getSalt()));
  102. user.setUserRecord(new UserRecord());
  103. user.getUserRecord().setUser(user);
  104. user.getUserRecord().setUserUU(user.getUserUU());
  105. userDao.save(user);
  106. userLog.info(user, Type.UPDATE_REGISTER.getValue());
  107. // 同步到各个应用
  108. return syncUserInfo(user.getUserUU(), noEncryPwd, "个人注册");
  109. }
  110. @Override
  111. public String getEncryPassword(String format, String noEncryPwd, String salt) {
  112. if (StringUtils.isEmpty(format)) {
  113. return noEncryPwd;
  114. }
  115. // 超过32认为是已加密过的密文
  116. if (noEncryPwd.length() >= 32) {
  117. /// 之后添加日志时恢复
  118. //logger.error("用户密码加密", String.format("传递过来的密码(%s)必须是未加密的明文", noEncryPwd));
  119. throw new VisibleError("密码过长,请重新输入");
  120. }
  121. // $password{$salt}
  122. String password = format.replace(Const.ENCRY_PARAM_PASSWORD, noEncryPwd);
  123. password = password.replace(Const.ENCRY_PARAM_SALT, salt == null ? "" : salt);
  124. return MD5.toMD5(password);
  125. }
  126. @Override
  127. public User save(User user) {
  128. user = userDao.save(user);
  129. return syncUserInfo(user, null, "修改用户信息");
  130. }
  131. @Override
  132. public void checkPassword(Long userUU, String password, boolean isEncry) {
  133. // 根据用户uu号找到旧数据
  134. User oldUser = userDao.findByUserUU(userUU);
  135. if (oldUser == null) {
  136. throw new VisibleError("用户名或密码错误");
  137. }
  138. // 校验密码
  139. checkPassword(oldUser, password, isEncry);
  140. }
  141. @Override
  142. public void checkPasswordByMobile(String mobile, String password, boolean isEncry) {
  143. // 找到用户
  144. User oldUser = userDao.findByMobile(mobile);
  145. if (oldUser == null) {
  146. throw new VisibleError("用户名或密码错误");
  147. }
  148. // 校验密码
  149. checkPassword(oldUser, password, isEncry);
  150. }
  151. @Override
  152. public void checkPasswordByEmail(String email, String password, boolean isEncry) {
  153. // 找到用户
  154. List<User> oldUsers = userDao.findByEmailAndEmailValidCode(email, (short) Status.AUTHENTICATED.getCode());
  155. if (CollectionUtils.isEmpty(oldUsers)) {
  156. throw new VisibleError("该邮箱未认证,请使用手机号登录");
  157. }
  158. // 校验密码
  159. for (User oldUser : oldUsers) {
  160. checkPassword(oldUser, password, isEncry);
  161. }
  162. }
  163. @Override
  164. public int getPwdErrorCount(String username) {
  165. User user = findByUsername(username);
  166. if (user == null) {
  167. throw new VisibleError("用户名不存在");
  168. }
  169. if (user.getUserRecord() == null) {
  170. return 0;
  171. }
  172. return user.getUserRecord().getPwdErrorCount();
  173. }
  174. @Override
  175. public User findByUsername(String username) {
  176. String type = AccountTypeUtils.getAccountType(username);
  177. User user = null;
  178. if (AccountTypeUtils.MOBILE.equals(type)) {
  179. // 手机号
  180. user = userDao.findByMobile(username);
  181. } else if (AccountTypeUtils.EMAIL.equals(type)) {
  182. // 邮箱
  183. List<User> users = userDao.findByEmailAndEmailValidCode(username, (short) Status.AUTHENTICATED.getCode());
  184. // 认证邮箱只有一条记录,直接选择第一个
  185. if (!CollectionUtils.isEmpty(users)) {
  186. user = users.get(0);
  187. }
  188. } else if (AccountTypeUtils.UU_NUMBER.equals(type)) {
  189. // uu号
  190. user = userDao.findByUserUU(Long.valueOf(username));
  191. }
  192. return user;
  193. }
  194. /**
  195. * 校验用户密码
  196. *
  197. * @param oldUser 用户信息
  198. * @param password 需要校验的密码
  199. * @param isEncry 需校验的密码是否被加密
  200. */
  201. private void checkPassword(User oldUser, String password, boolean isEncry) {
  202. // 密码未加密,转换成加密后的密码
  203. String encryPassword = password;
  204. if (!isEncry) {
  205. encryPassword = getEncryPassword(Const.ENCRY_FORMAT, password, oldUser.getSalt());
  206. }
  207. // 校验密码
  208. if (!encryPassword.equals(oldUser.getPassword())) {
  209. throw new VisibleError("密码不一致");
  210. }
  211. }
  212. @Override
  213. public UserRecord save(UserRecord userRecord) {
  214. return userRecordDao.save(userRecord);
  215. }
  216. @Override
  217. public User findOne(Long userUU) {
  218. return userDao.findOne(userUU);
  219. }
  220. @Override
  221. public boolean realNameIsValid(String realName) {
  222. User user = userDao.findByRealName(realName);
  223. if (user != null && user.getIdentityValidCode() == Status.AUTHENTICATED.getCode()) {
  224. return true;
  225. }
  226. return false;
  227. }
  228. @Override
  229. public boolean idCardIsValid(String idCard) {
  230. User user = userDao.findByIdCard(idCard);
  231. if (user != null && user.getIdentityValidCode() == Status.AUTHENTICATED.getCode()) {
  232. return true;
  233. }
  234. return false;
  235. }
  236. @Override
  237. public void submitIdValidInfo(User user) {
  238. // 校验企业名和营业执照是否被认证
  239. boolean isValid = realNameIsValid(user.getRealName());
  240. if (isValid) {
  241. throw new VisibleError("该真实姓名已被认证,请确认");
  242. }
  243. isValid = idCardIsValid(user.getIdCard());
  244. if (isValid) {
  245. throw new VisibleError("该身份证号已被认证,请确认");
  246. }
  247. User oldUser = userDao.findByUserUU(user.getUserUU());
  248. oldUser.setIdentityValidCode((short) Status.TO_BE_CERTIFIED.getCode());
  249. oldUser.setRealName(user.getRealName());
  250. oldUser.setIdCard(user.getIdCard());
  251. this.save(oldUser);
  252. // 保存日志
  253. userValidService.submitValid(user);
  254. }
  255. @Override
  256. public void updateMobile(Long userUU, String newMobile) {
  257. // 获取用户信息
  258. User user = userDao.findOne(userUU);
  259. if (user == null) {
  260. throw new VisibleError("用户不存在");
  261. }
  262. // 修改手机号
  263. user.setMobile(newMobile);
  264. user.setMobileValidCode((short) Status.AUTHENTICATED.getCode());
  265. // 保存用户信息
  266. userDao.save(user);
  267. // 保存日志
  268. userLog.info(user, Type.UPDATE_MOBILE.getValue());
  269. // 同步到各个应用
  270. syncUserInfo(user.getUserUU(), null, "个人注册");
  271. }
  272. @Override
  273. public void updateEmail(Long userUU, String newEmail) {
  274. // 获取用户信息
  275. User user = userDao.findOne(userUU);
  276. if (user == null) {
  277. throw new VisibleError("用户不存在");
  278. }
  279. // 修改手机号
  280. user.setEmail(newEmail);
  281. user.setEmailValidCode((short) Status.AUTHENTICATED.getCode());
  282. // 保存用户信息
  283. userDao.save(user);
  284. // 保存日志
  285. userLog.info(user, Type.UPDATE_EMAIL.getValue());
  286. // 同步信息到各应用
  287. syncUserInfo(user.getUserUU(), null, "修改邮箱");
  288. }
  289. @Override
  290. public Page<User> findMemberBySpaceUU(int page, int size, final Long spaceUU) {
  291. Pageable pageable = PageInfo.pageRequest(new PageRequest(page, size));
  292. Page<User> pUsers = userDao.findAll(new Specification<User>() {
  293. @Override
  294. public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
  295. List<Predicate> list = new ArrayList<>();
  296. list.add(cb.equal(root.join("userSpaces", JoinType.INNER).get("spaceUU").as(Long.class), spaceUU));
  297. Predicate[] predicates = new Predicate[list.size()];
  298. predicates = list.toArray(predicates);
  299. return cb.and(predicates);
  300. }
  301. }, pageable);
  302. return new PageInfo<User>(pUsers.getContent(), pageable, pUsers.getTotalElements());
  303. }
  304. @Override
  305. public void bindUserspace(String appId, Long userUU, Long spaceUU) {
  306. // 找到用户和企业
  307. User user = findOne(userUU);
  308. Userspace userspace = userspaceService.findOne(spaceUU);
  309. // 将企业添加到用户列表上
  310. Set<Userspace> userspaces = user.getUserSpaces();
  311. userspaces.add(userspace);
  312. // 保存
  313. userDao.save(user);
  314. syncUserBindSpace(userUU, spaceUU);
  315. // 保存日志
  316. userLog.info(user, Type.BIND_USERSPACE.getValue()+spaceUU);
  317. }
  318. /**
  319. * 同步用户绑定企业关系
  320. * @param userUU 用户uu号
  321. * @param spaceUU 企业uu号
  322. */
  323. private void syncUserBindSpace(Long userUU, Long spaceUU) {
  324. syncRelation(userUU, spaceUU, "bind");
  325. }
  326. /**
  327. * 同步用户解除绑定企业关系
  328. * @param userUU 用户uu号
  329. * @param spaceUU 企业uu号
  330. */
  331. private void syncUserUnbindSpace(Long userUU, Long spaceUU) {
  332. syncRelation(userUU, spaceUU, "unbind");
  333. }
  334. /**
  335. * 同步用户与企业的关系
  336. * @param userUU 用户uu号
  337. * @param spaceUU 企业uu号
  338. * @param type 类型 (bind or unbind)
  339. */
  340. private void syncRelation(final Long userUU, final Long spaceUU, final String type) {
  341. List<String> apps = appService.findUid();
  342. ExecuteUtils.execute(new ICallable<Void, String>() {
  343. @Override
  344. public Void call(String appId) {
  345. App tempApp = appService.findOne(appId);
  346. if (tempApp != null && StringUtils.isEmpty(tempApp.getUserControl())
  347. && !StringUtils.isEmpty(tempApp.getBackRelationUrl())) {
  348. String url = tempApp.getBackRelationUrl();
  349. ModelMap formData = new ModelMap();
  350. formData.put("userUU", userUU);
  351. formData.put("spaceUU", spaceUU);
  352. formData.put("type", type);
  353. HttpUtil.ResponseWrap res = null;
  354. try {
  355. res = HttpUtil.doPost(url, formData, 10000);
  356. if (!res.isSuccess()) {
  357. syncLog.error(appId, "同步绑定信息失败", JSON.toJSONString(formData), res.getContent());
  358. } else {
  359. syncLog.info(appId, "同步绑定信息成功", JSON.toJSONString(formData));
  360. }
  361. } catch (Exception e) {
  362. syncLog.error(appId, "同步绑定信息失败", JSON.toJSONString(formData), e.getMessage());
  363. }
  364. }
  365. return null;
  366. }
  367. }, apps);
  368. }
  369. @Override
  370. public void unbindUserspace(Long userUU, Long spaceUU) {
  371. // 找到用户和企业
  372. User user = findOne(userUU);
  373. if (user == null) {
  374. throw new VisibleError("未找到用户信息");
  375. }
  376. Userspace userspace = userspaceService.findOne(spaceUU);
  377. if (userspace == null) {
  378. throw new VisibleError("未找到企业信息");
  379. }
  380. // 将企业添加到用户列表上
  381. Set<Userspace> userspaces = user.getUserSpaces();
  382. userspaces.remove(userspace);
  383. // 保存
  384. userDao.save(user);
  385. syncUserUnbindSpace(userUU, spaceUU);
  386. // 保存日志
  387. userLog.info(user, Type.UNBIND_USERSPACE.getValue()+spaceUU);
  388. }
  389. @Override
  390. public void setQuestion(Long userUU, List<UserQuestion> questions) {
  391. // 找到用户密保
  392. User user = userDao.findOne(userUU);
  393. List<UserQuestion> userQuestions = user.getQuestions();
  394. // 清空旧的并添加新的
  395. if (CollectionUtils.isEmpty(userQuestions)) {
  396. user.setQuestions(questions);
  397. } else {
  398. for (int i=0; i<questions.size(); i++) {
  399. if (userQuestions.get(i) == null) {
  400. user.getQuestions().add(questions.get(i));
  401. } else {
  402. userQuestions.get(i).setQuestion(questions.get(i).getQuestion());
  403. userQuestions.get(i).setAnswer(questions.get(i).getAnswer());
  404. userQuestions.get(i).setSort(questions.get(i).getSort());
  405. }
  406. }
  407. }
  408. // 保存并添加日志
  409. user = userDao.save(user);
  410. syncUserInfo(user, null, "修改密保");
  411. userLog.info(user, Type.UPDATE_QUESTION.getValue(), JSON.toJSONString(user.getQuestions()));
  412. }
  413. @Override
  414. public List<String> findRepeatEmail() {
  415. return userDao.findRepeatEmail();
  416. }
  417. @Override
  418. public List<User> findByEmail(String email) {
  419. return userDao.findByEmail(email);
  420. }
  421. @Override
  422. public User updatePassword(Long userUU, String noEncryPwd) {
  423. User user = userDao.findOne(userUU);
  424. if (user == null) {
  425. throw new VisibleError("该用户不存在");
  426. }
  427. user.setPassword(getEncryPassword(Const.ENCRY_FORMAT, noEncryPwd, user.getSalt()));
  428. user = syncUserInfo(user , noEncryPwd, "用户修改密码");
  429. return userDao.save(user);
  430. }
  431. @Override
  432. public List<UserSpaceDetailInfo> findUserByTels(List<String> tels) {
  433. // 获取用户列表
  434. List<User> users = userDao.findUsersByTels(tels);
  435. if (CollectionUtils.isEmpty(users)) {
  436. return null;
  437. }
  438. List<UserSpaceDetailInfo> data = new ArrayList<>(users.size());
  439. UserSpaceDetailInfo info;
  440. // 遍历用户列表取数据
  441. for (User user : users) {
  442. info = new UserSpaceDetailInfo();
  443. Set<Userspace> spaces = user.getUserSpaces();
  444. if (!CollectionUtils.isEmpty(spaces)) {
  445. // 有企业的话随便取一个,uu互联需求
  446. Iterator<Userspace> iterator = spaces.iterator();
  447. Userspace userspace = iterator.next();
  448. info.setAddress(userspace.getRegAddress());
  449. info.setCompany(userspace.getSpaceName());
  450. }
  451. info.setEmail(user.getEmail());
  452. info.setImid(user.getImId());
  453. info.setUsertel(user.getMobile());
  454. info.setUsername(user.getVipName());
  455. data.add(info);
  456. }
  457. return data;
  458. }
  459. /**
  460. * 同步用户信息到各个应用
  461. * @param userUU 用户uu号
  462. * @param noEncryPwd 未加密密码,用于同步im
  463. * @param msg 同步信息描述,用户区分同步类型
  464. */
  465. private User syncUserInfo(Long userUU, String noEncryPwd, String msg) {
  466. return syncUserInfo(findOne(userUU), noEncryPwd, msg);
  467. }
  468. /**
  469. * 同步用户信息到各个应用
  470. * @param user 用户信息
  471. * @param noEncryPwd 未加密密码,用于同步im
  472. * @param msg 同步信息描述,用户区分同步类型
  473. */
  474. private User syncUserInfo(User user, String noEncryPwd, final String msg) {
  475. List<String> apps = appService.findUid();
  476. final boolean hasQuestion = user.getQuestions() != null;
  477. try {
  478. // 同步信息到im
  479. String imId = syncUserToIm(user, noEncryPwd);
  480. user.setImId(imId);
  481. user = userDao.save(user);
  482. } catch (Exception e) {
  483. e.printStackTrace();
  484. }
  485. final User finalUser = user;
  486. ExecuteUtils.execute(new ICallable<Void, String>() {
  487. @Override
  488. public Void call(String appId) {
  489. App tempApp = appService.findOne(appId);
  490. if (tempApp != null && StringUtils.isEmpty(tempApp.getUserControl())
  491. && !StringUtils.isEmpty(tempApp.getBackUserUrl())) {
  492. String url = tempApp.getBackUserUrl();
  493. JSONObject formData = JSON.parseObject(JSON.toJSONString(finalUser));
  494. formData.put("password", finalUser.getPassword());
  495. formData.put("hasQuestion", hasQuestion);
  496. HttpUtil.ResponseWrap res = null;
  497. try {
  498. res = HttpUtil.doPost(url, formData, 10000);
  499. if (!res.isSuccess()) {
  500. syncLog.error(appId, msg + ",同步用户信息失败", JSON.toJSONString(finalUser), res.getContent());
  501. } else {
  502. syncLog.info(appId, msg + ",同步用户信息成功", JSON.toJSONString(finalUser));
  503. }
  504. } catch (Exception e) {
  505. syncLog.error(appId, msg + ",同步用户信息失败", JSON.toJSONString(finalUser), e.getMessage());
  506. }
  507. }
  508. return null;
  509. }
  510. }, apps);
  511. return user;
  512. }
  513. private String syncUserToIm(User user, String noEncryPwd) throws Exception {
  514. String appId = "im";
  515. App app = appService.findOne(appId);
  516. if (!StringUtils.isEmpty(app.getBackUserUrl())) {
  517. String url = app.getBackUserUrl();
  518. HttpUtil.ResponseWrap res = null;
  519. ModelMap formData = new ModelMap();
  520. formData.put("email", user.getEmail());
  521. formData.put("idCard", user.getIdCard());
  522. formData.put("name", user.getVipName());
  523. formData.put("sex", user.getSex());
  524. formData.put("mobile", user.getMobile());
  525. formData.put("password", noEncryPwd);
  526. formData.put("dialectUID", user.getImId());
  527. res = HttpUtil.doPost(url, formData, 10000);
  528. if (!res.isSuccess()) {
  529. throw new Exception(res.getContent());
  530. } else {
  531. JSONObject obj = JSON.parseObject(res.getContent());
  532. return String.valueOf(obj.get("dialectUID"));
  533. }
  534. }
  535. return null;
  536. }
  537. public UserView findOneView(Long userUU) {
  538. User user = findOne(userUU);
  539. return user.toView();
  540. }
  541. }