PersonalRegisterController.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. package com.uas.sso.controller;
  2. import com.alibaba.fastjson.JSON;
  3. import com.uas.sso.SSOHelper;
  4. import com.uas.sso.SSOToken;
  5. import com.uas.sso.entity.register.SmsPersonalRegister;
  6. import com.uas.sso.core.Step;
  7. import com.uas.sso.core.Type;
  8. import com.uas.sso.core.PasswordStrength;
  9. import com.uas.sso.entity.App;
  10. import com.uas.sso.entity.Token;
  11. import com.uas.sso.entity.User;
  12. import com.uas.sso.entity.UserAccount;
  13. import com.uas.sso.foreign.entity.ForeignInfo;
  14. import com.uas.sso.logging.LoggerManager;
  15. import com.uas.sso.logging.RegisterBufferedLogger;
  16. import com.uas.sso.service.AppService;
  17. import com.uas.sso.service.PersonalAccountService;
  18. import com.uas.sso.service.UserService;
  19. import com.uas.sso.util.CaptchaUtil;
  20. import com.uas.sso.util.DomainUtil;
  21. import com.uas.sso.util.IpUtils;
  22. import com.uas.sso.util.MessageUtils;
  23. import com.uas.sso.util.PasswordLevelUtils;
  24. import com.uas.sso.util.StringUtil;
  25. import com.uas.sso.util.encry.Md5Utils;
  26. import org.slf4j.Logger;
  27. import org.slf4j.LoggerFactory;
  28. import org.springframework.beans.factory.annotation.Autowired;
  29. import org.springframework.stereotype.Controller;
  30. import org.springframework.ui.ModelMap;
  31. import org.springframework.util.StringUtils;
  32. import org.springframework.web.bind.annotation.PostMapping;
  33. import org.springframework.web.bind.annotation.RequestMapping;
  34. import org.springframework.web.bind.annotation.RequestMethod;
  35. import org.springframework.web.bind.annotation.ResponseBody;
  36. import org.springframework.web.bind.annotation.RestController;
  37. import java.io.UnsupportedEncodingException;
  38. import java.net.URLDecoder;
  39. import java.util.List;
  40. import java.util.Optional;
  41. import java.util.Random;
  42. /**
  43. * 个人注册controller
  44. *
  45. * @author uas
  46. * @date 2018/1/2
  47. */
  48. @RestController
  49. @RequestMapping("/sso/personal/register")
  50. public class PersonalRegisterController extends BaseController {
  51. @Autowired
  52. private UserService userService;
  53. @Autowired
  54. private PersonalAccountService personalAccountService;
  55. @Autowired
  56. private AppService appService;
  57. private RegisterBufferedLogger registerLogger = LoggerManager.getLogger(RegisterBufferedLogger.class);
  58. private final static Logger LOGGER = LoggerFactory.getLogger(PersonalRegisterController.class);
  59. /**
  60. * 验证码存session的可以
  61. */
  62. private static final String RESET_CAPTCHA = "resetCaptcha";
  63. /**
  64. * 注册个人信息
  65. *
  66. * @param user 用户信息(需要会员名,手机号,手机号所属区域,密码)
  67. * @param appId 注册应用标志
  68. * @param code 验证码
  69. * @param token 验证码tokenId
  70. * @return 成功:success(),失败:error("错误码", "错误信息")
  71. */
  72. @RequestMapping(method = RequestMethod.POST)
  73. @ResponseBody
  74. public ModelMap register(User user, String appId, String code, String token, String baseUrl, String t, String returnUrl) throws UnsupportedEncodingException {
  75. // 获取参数
  76. String vipName = user.getVipName();
  77. String mobile = user.getMobile();
  78. String mobileArea = user.getMobileArea();
  79. String password = user.getPassword();
  80. // 参数空校验
  81. if (StringUtils.isEmpty(vipName)) {
  82. return error("会员名不能为空");
  83. }
  84. if (StringUtils.isEmpty(password)) {
  85. return error("密码不能为空");
  86. }
  87. if (StringUtils.isEmpty(mobile)) {
  88. return error("手机号不能为空");
  89. }
  90. // 校验手机号
  91. checkMobile(mobile, mobileArea);
  92. // 校验验证码
  93. checkMobileCode(token, mobile, code);
  94. // 校验密码
  95. if (PasswordStrength.WEAK.equals(PasswordLevelUtils.checkPasswordLevel(password))) {
  96. return error("密码须为8-20字符的英文、数字混合");
  97. }
  98. // 设置第三方id
  99. if (!StringUtils.isEmpty(t)) {
  100. Token unionidToken = tokenService.findOne(t);
  101. Optional<ForeignInfo> foreignInfo = Optional.ofNullable(unionidToken).map(value -> (ModelMap) unionidToken.getBind()).map(value -> (ForeignInfo) value.get("data"));
  102. if (!foreignInfo.isPresent()) {
  103. return error("参数错误,绑定失败");
  104. }
  105. userService.setForeignOpenId(user, foreignInfo.get());
  106. }
  107. // 注册并添加注册日志
  108. appId = StringUtils.isEmpty(appId) ? "sso" : appId;
  109. user.setFromIp(IpUtils.getIp(request));
  110. user.setFromUrl(URLDecoder.decode(returnUrl, "utf-8"));
  111. user = userService.register(user, appId);
  112. registerLogger.info(Type.REGISTER_PERSONAL.getValue(), Step.FIRST.getValue(), "个人注册成功", user, user.getFromApp());
  113. // 注册成功后删除验证码token
  114. if (!StringUtils.isEmpty(t)) {
  115. tokenService.delete(t);
  116. }
  117. tokenService.delete(token);
  118. // 判断应用是否存在
  119. App app = appService.findOne(appId);
  120. if (app == null) {
  121. LOGGER.warn("个人注册,应用{}不存在,注册用户:{}", appId, user.getUserUU());
  122. return success();
  123. }
  124. // 登录并返回数据
  125. UserAccount userAccount = personalAccountService.findOneByUserUU(appId, user.getUserUU());
  126. userAccount.setLastLoginTime(System.currentTimeMillis());
  127. List<String> loginUrls = appService.findAllLoginUrl();
  128. SSOToken st = new SSOToken(request, userAccount.getMobile());
  129. st.setData(JSON.toJSONString(userAccount));
  130. SSOHelper.getSSOService().getConfig().setCookieDomain(DomainUtil.getFirstDomain(request));
  131. SSOHelper.setSSOCookie(request, response, st, true);
  132. ModelMap data = new ModelMap();
  133. data.addAttribute("data", userAccount)
  134. .addAttribute("loginUrls", loginUrls)
  135. .addAttribute("currentUrl", baseUrl);
  136. LOGGER.info("用户({})注册并登录成功,时间:{}", user.getUserUU(), System.currentTimeMillis());
  137. return success(data);
  138. }
  139. @PostMapping("/sms")
  140. public ModelMap register(SmsPersonalRegister personalRegister) throws UnsupportedEncodingException {
  141. User user = new User();
  142. String mobile = personalRegister.getMobile();
  143. String password = getPassword(mobile.substring(mobile.length() - 3, mobile.length()));
  144. user.setVipName(mobile);
  145. user.setMobile(mobile);
  146. user.setPassword(password);
  147. ModelMap response = register(user, personalRegister.getAppId(), personalRegister.getCode(), personalRegister.getToken(),
  148. personalRegister.getBaseUrl(), personalRegister.getT(), personalRegister.getReturnUrl());
  149. MessageUtils.sendSms("templateForSendSmsAfterRegisterSuccess", mobile, mobile, password);
  150. return response;
  151. }
  152. /**
  153. * 获取密码
  154. * @param suffix 密码后缀
  155. * @return
  156. */
  157. private String getPassword(String suffix) {
  158. Random random = new Random();
  159. String val = "";
  160. // 生成4个字母
  161. for (int i=0; i<3; i++) {
  162. int choice = random.nextInt(2) % 2 == 0 ? 65 : 97;
  163. val = val + (char)(choice + random.nextInt(26));
  164. }
  165. // 3个数字
  166. String number = random.nextInt(999) + 1000 + "";
  167. number = number.substring(number.length() - 3, number.length());
  168. val = val + number;
  169. // 后缀
  170. val = val + suffix;
  171. return val;
  172. }
  173. /**
  174. * 获取验证码
  175. *
  176. * @param mobile 手机号
  177. * @param code 图片验证码
  178. * @param sign 签名,签名不对不发送验证码
  179. * @return success(tokenId)
  180. */
  181. @RequestMapping(value = "/checkCode", method = RequestMethod.GET)
  182. @ResponseBody
  183. public ModelMap getCode(String mobile, String code, String sign) {
  184. // 参数校验
  185. if (StringUtils.isEmpty(mobile)) {
  186. return error("请输入手机号");
  187. }
  188. // 校验图片验证码
  189. Token captchaToken = tokenService.findOne(request.getSession().getId());
  190. if (captchaToken == null) {
  191. return error("图片验证码过期");
  192. }
  193. if (code != null && !code.equalsIgnoreCase((String) captchaToken.getBind())) {
  194. return error("请输入正确的验证码");
  195. }
  196. tokenService.delete(request.getSession().getId());
  197. // 校验发送短信频率,60秒一次,key为#{sessionId}_#{类名}
  198. String key = request.getSession().getId() + "_" + this.getClass().getSimpleName();
  199. Token rateToken = tokenService.findOne(key);
  200. if (rateToken != null) {
  201. return error("验证码发送间隔过快");
  202. }
  203. // 获取验证码,根据签名判断是否需要获取验证码
  204. String str = "{mobile=" + mobile + ",code=" + code + ",salt=sso}";
  205. String existSign = Md5Utils.encode(str, null);
  206. String token;
  207. if (existSign.equals(sign)) {
  208. token = getMobileToken(mobile);
  209. } else {
  210. token = StringUtil.uuid();
  211. LOGGER.warn("签名不通过!加密参数:{},sign:{}", str, sign);
  212. }
  213. // 设置发送短信频率
  214. rateToken = new Token(key, "", 60);
  215. tokenService.save(rateToken);
  216. // 设置返回数据
  217. ModelMap data = new ModelMap();
  218. data.put("token", token);
  219. data.put("code", request.getSession().getAttribute("code"));
  220. request.getSession().setAttribute("token", token);
  221. return data;
  222. }
  223. /**
  224. * 校验验证码
  225. *
  226. * @param code 验证码
  227. * @param token 验证码tokenId
  228. * @return 验证成功:success(),验证失败:error("错误信息")
  229. */
  230. @RequestMapping(value = "/checkCode", method = RequestMethod.POST)
  231. @ResponseBody
  232. public ModelMap checkCode(String token, String mobile, String code) {
  233. // 校验token是否正确
  234. String sessionToken = (String) request.getSession().getAttribute("token");
  235. if (StringUtils.isEmpty(sessionToken) || !sessionToken.equals(token)) {
  236. return error("请重新获取验证码");
  237. }
  238. // 校验验证码
  239. checkMobileCode(token, mobile, code);
  240. // 设置返回值
  241. return success();
  242. }
  243. }