UserServiceImpl.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  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.AppService;
  18. import com.uas.sso.service.UserService;
  19. import com.uas.sso.service.UserValidService;
  20. import com.uas.sso.service.UserspaceService;
  21. import com.uas.sso.util.AccountTypeUtils;
  22. import com.uas.sso.util.ExecuteUtils;
  23. import org.springframework.beans.factory.annotation.Autowired;
  24. import org.springframework.data.domain.Page;
  25. import org.springframework.data.domain.PageRequest;
  26. import org.springframework.data.domain.Pageable;
  27. import org.springframework.data.jpa.domain.Specification;
  28. import org.springframework.stereotype.Service;
  29. import org.springframework.util.CollectionUtils;
  30. import org.springframework.util.StringUtils;
  31. import com.uas.sso.exception.AccountException;
  32. import javax.persistence.criteria.*;
  33. import java.sql.Timestamp;
  34. import java.util.ArrayList;
  35. import java.util.List;
  36. import java.util.Set;
  37. /**
  38. * 用户service实现类
  39. *
  40. * @author wangmh
  41. * @date 2018/1/2
  42. */
  43. @Service
  44. public class UserServiceImpl implements UserService {
  45. @Autowired
  46. private UserDao userDao;
  47. @Autowired
  48. private UserRecordDao userRecordDao;
  49. @Autowired
  50. private UserValidService userValidService;
  51. @Autowired
  52. private UserspaceService userspaceService;
  53. @Autowired
  54. private AppService appService;
  55. private UserBufferedLogger userLog = LoggerManager.getLogger(UserBufferedLogger.class);
  56. private SyncBufferedLogger syncLog = LoggerManager.getLogger(SyncBufferedLogger.class);
  57. @Override
  58. public User findByMobile(String mobile, String mobileArea) {
  59. return userDao.findByMobileAndMobileArea(mobile, mobileArea);
  60. }
  61. @Override
  62. public User findByMobile(String mobile) {
  63. return userDao.findByMobile(mobile);
  64. }
  65. @Override
  66. public boolean mobileHasRegistered(String mobile) {
  67. User user = userDao.findByMobile(mobile);
  68. if (user == null) {
  69. return false;
  70. }
  71. return true;
  72. }
  73. @Override
  74. public boolean emailHasRegistered(String email) {
  75. List<User> users = userDao.findByEmailAndEmailValidCode(email, (short) Status.AUTHENTICATED.getCode());
  76. if (CollectionUtils.isEmpty(users)) {
  77. return false;
  78. }
  79. return true;
  80. }
  81. @Override
  82. public User register(User user) {
  83. // 校验手机号是否被注册
  84. if (mobileHasRegistered(user.getMobile())) {
  85. throw new VisibleError("该手机号已被注册");
  86. }
  87. // 由于现在不考虑手机号所属区域,默认为中国大陆
  88. if (StringUtils.isEmpty(user.getMobileArea())) {
  89. user.setMobileArea(Const.CONTINENT);
  90. }
  91. // 设置基本属性,手机号默认已认证
  92. user.setRegisterDate(new Timestamp(System.currentTimeMillis()));
  93. Long uu = userDao.findMaxUU();
  94. user.setUserUU(uu == null ? 10000 : (uu + 1));
  95. user.setSalt(String.valueOf(user.getUserUU()));
  96. user.setMobileValidCode((short) Status.AUTHENTICATED.getCode());
  97. user.setEmailValidCode((short) Status.NOT_APPLYING.getCode());
  98. user.setIdentityValidCode((short) Status.NOT_APPLYING.getCode());
  99. user.setPassword(getEncryPassword(Const.ENCRY_FORMAT, user.getPassword(), user.getSalt()));
  100. user.setUserRecord(new UserRecord());
  101. userDao.save(user);
  102. userLog.info(user, Type.UPDATE_REGISTER.getValue());
  103. // 同步到各个应用
  104. syncUserInfo(user.getUserUU(), "个人注册");
  105. return user;
  106. }
  107. @Override
  108. public String getEncryPassword(String format, String noEncryPwd, String salt) {
  109. if (StringUtils.isEmpty(format)) {
  110. return noEncryPwd;
  111. }
  112. // 超过32认为是已加密过的密文
  113. if (noEncryPwd.length() >= 32) {
  114. /// 之后添加日志时恢复
  115. //logger.error("用户密码加密", String.format("传递过来的密码(%s)必须是未加密的明文", noEncryPwd));
  116. throw new AccountException("invalid password");
  117. }
  118. // $password{$salt}
  119. String password = format.replace(Const.ENCRY_PARAM_PASSWORD, noEncryPwd);
  120. password = password.replace(Const.ENCRY_PARAM_SALT, salt == null ? "" : salt);
  121. return MD5.toMD5(password);
  122. }
  123. @Override
  124. public User save(User user) {
  125. user = userDao.save(user);
  126. syncUserInfo(user.toView(), "修改用户信息");
  127. return user;
  128. }
  129. @Override
  130. public void checkPassword(Long userUU, String password, boolean isEncry) {
  131. // 根据用户uu号找到旧数据
  132. User oldUser = userDao.findByUserUU(userUU);
  133. if (oldUser == null) {
  134. throw new VisibleError("用户名或密码错误");
  135. }
  136. // 校验密码
  137. checkPassword(oldUser, password, isEncry);
  138. }
  139. @Override
  140. public void checkPasswordByMobile(String mobile, String password, boolean isEncry) {
  141. // 找到用户
  142. User oldUser = userDao.findByMobile(mobile);
  143. if (oldUser == null) {
  144. throw new VisibleError("用户名或密码错误");
  145. }
  146. // 校验密码
  147. checkPassword(oldUser, password, isEncry);
  148. }
  149. @Override
  150. public void checkPasswordByEmail(String email, String password, boolean isEncry) {
  151. // 找到用户
  152. List<User> oldUsers = userDao.findByEmailAndEmailValidCode(email, (short) Status.AUTHENTICATED.getCode());
  153. if (CollectionUtils.isEmpty(oldUsers)) {
  154. throw new VisibleError("该邮箱未认证,请使用手机号登录");
  155. }
  156. // 校验密码
  157. for (User oldUser : oldUsers) {
  158. checkPassword(oldUser, password, isEncry);
  159. }
  160. }
  161. @Override
  162. public int getPwdErrorCount(String username) {
  163. User user = findByUsername(username);
  164. if (user == null) {
  165. throw new VisibleError("用户名不存在");
  166. }
  167. if (user.getUserRecord() == null) {
  168. return 0;
  169. }
  170. return user.getUserRecord().getPwdErrorCount();
  171. }
  172. @Override
  173. public User findByUsername(String username) {
  174. String type = AccountTypeUtils.getAccountType(username);
  175. User user = null;
  176. if (AccountTypeUtils.MOBILE.equals(type)) {
  177. // 手机号
  178. user = userDao.findByMobile(username);
  179. } else if (AccountTypeUtils.EMAIL.equals(type)) {
  180. // 邮箱
  181. List<User> users = userDao.findByEmailAndEmailValidCode(username, (short) Status.AUTHENTICATED.getCode());
  182. // 认证邮箱只有一条记录,直接选择第一个
  183. if (!CollectionUtils.isEmpty(users)) {
  184. user = users.get(0);
  185. }
  186. } else if (AccountTypeUtils.UU_NUMBER.equals(type)) {
  187. // uu号
  188. user = userDao.findByUserUU(Long.valueOf(type));
  189. }
  190. return user;
  191. }
  192. /**
  193. * 校验用户密码
  194. *
  195. * @param oldUser 用户信息
  196. * @param password 需要校验的密码
  197. * @param isEncry 需校验的密码是否被加密
  198. */
  199. private void checkPassword(User oldUser, String password, boolean isEncry) {
  200. // 密码未加密,转换成加密后的密码
  201. String encryPassword = password;
  202. if (!isEncry) {
  203. encryPassword = getEncryPassword(Const.ENCRY_FORMAT, password, oldUser.getSalt());
  204. }
  205. // 校验密码
  206. if (!encryPassword.equals(oldUser.getPassword())) {
  207. throw new VisibleError("密码不一致");
  208. }
  209. }
  210. @Override
  211. public void save(UserRecord userRecord) {
  212. userRecordDao.save(userRecord);
  213. }
  214. @Override
  215. public User findOne(Long userUU) {
  216. return userDao.findOne(userUU);
  217. }
  218. @Override
  219. public boolean realNameIsValid(String realName) {
  220. User user = userDao.findByRealName(realName);
  221. if (user != null && user.getIdentityValidCode() == Status.AUTHENTICATED.getCode()) {
  222. return true;
  223. }
  224. return false;
  225. }
  226. @Override
  227. public boolean idCardIsValid(String idCard) {
  228. User user = userDao.findByIdCard(idCard);
  229. if (user != null && user.getIdentityValidCode() == Status.AUTHENTICATED.getCode()) {
  230. return true;
  231. }
  232. return false;
  233. }
  234. @Override
  235. public void submitIdValidInfo(User user) {
  236. // 校验企业名和营业执照是否被认证
  237. boolean isValid = realNameIsValid(user.getRealName());
  238. if (isValid) {
  239. throw new VisibleError("该真实姓名已被认证,请确认");
  240. }
  241. isValid = idCardIsValid(user.getIdCard());
  242. if (isValid) {
  243. throw new VisibleError("该身份证号已被认证,请确认");
  244. }
  245. // 保存日志
  246. userValidService.submitValid(user);
  247. }
  248. @Override
  249. public void updateMobile(Long userUU, String newMobile) {
  250. // 获取用户信息
  251. User user = userDao.findOne(userUU);
  252. if (user == null) {
  253. throw new VisibleError("用户不存在");
  254. }
  255. // 修改手机号
  256. user.setMobile(newMobile);
  257. user.setMobileValidCode((short) Status.AUTHENTICATED.getCode());
  258. // 保存用户信息
  259. userDao.save(user);
  260. // 保存日志
  261. userLog.info(user, Type.UPDATE_MOBILE.getValue());
  262. // 同步到各个应用
  263. syncUserInfo(user.getUserUU(), "个人注册");
  264. }
  265. @Override
  266. public void updateEmail(Long userUU, String newEmail) {
  267. // 获取用户信息
  268. User user = userDao.findOne(userUU);
  269. if (user == null) {
  270. throw new VisibleError("用户不存在");
  271. }
  272. // 修改手机号
  273. user.setEmail(newEmail);
  274. user.setEmailValidCode((short) Status.AUTHENTICATED.getCode());
  275. // 保存用户信息
  276. userDao.save(user);
  277. // 保存日志
  278. userLog.info(user, Type.UPDATE_EMAIL.getValue());
  279. // 同步信息到各应用
  280. syncUserInfo(user.getUserUU(), "个人注册");
  281. }
  282. @Override
  283. public Page<User> findMemberBySpaceUU(int page, int size, Long spaceUU) {
  284. Pageable pageable = new PageRequest(page, size);
  285. Page<User> pUsers = userDao.findAll(new Specification<User>() {
  286. @Override
  287. public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
  288. List<Predicate> list = new ArrayList<>();
  289. list.add(cb.equal(root.join("userSpaces", JoinType.INNER).get("spaceUU").as(Long.class), spaceUU));
  290. Predicate[] predicates = new Predicate[list.size()];
  291. predicates = list.toArray(predicates);
  292. return cb.and(predicates);
  293. }
  294. }, pageable);
  295. return pUsers;
  296. }
  297. @Override
  298. public void bindUserspace(Long userUU, Long spaceUU) {
  299. // 找到用户和企业
  300. User user = findOne(userUU);
  301. Userspace userspace = userspaceService.findOne(spaceUU);
  302. // 将企业添加到用户列表上
  303. Set<Userspace> userspaces = user.getUserSpaces();
  304. userspaces.add(userspace);
  305. // 保存
  306. userDao.save(user);
  307. }
  308. /**
  309. * 同步用户信息到各个应用
  310. * @param userUU 用户uu号
  311. * @param msg 同步信息描述,用户区分同步类型
  312. */
  313. private void syncUserInfo(Long userUU, String msg) {
  314. syncUserInfo(findOneView(userUU), msg);
  315. }
  316. /**
  317. * 同步用户信息到各个应用
  318. * @param userView 用户信息视图
  319. * @param msg 同步信息描述,用户区分同步类型
  320. */
  321. private void syncUserInfo(final UserView userView, final String msg) {
  322. List<String> apps = appService.findUid();
  323. ExecuteUtils.execute(new ICallable<Void, String>() {
  324. @Override
  325. public Void call(String appId) {
  326. App tempApp = appService.findOne(appId);
  327. if (tempApp != null && StringUtils.isEmpty(tempApp.getUserControl())
  328. && !StringUtils.isEmpty(tempApp.getBackUserUrl())) {
  329. String url = tempApp.getBackUserUrl();
  330. JSONObject formData = JSON.parseObject(JSON.toJSONString(userView));
  331. HttpUtil.ResponseWrap res = null;
  332. try {
  333. res = HttpUtil.doPost(url, formData, 30000);
  334. if (!res.isSuccess()) {
  335. syncLog.error(appId, msg + ",同步用户信息成功", JSON.toJSONString(userView), res.getContent());
  336. } else {
  337. syncLog.info(appId, msg + ",同步用户信息成功", JSON.toJSONString(userView));
  338. }
  339. } catch (Exception e) {
  340. syncLog.error(appId, msg + ",同步用户信息失败", JSON.toJSONString(userView), e.getMessage());
  341. }
  342. }
  343. return null;
  344. }
  345. }, apps);
  346. }
  347. public UserView findOneView(Long userUU) {
  348. User user = findOne(userUU);
  349. return user.toView();
  350. }
  351. }