package com.uas.sso.controller; import com.alibaba.fastjson.JSON; import com.uas.sso.SSOHelper; import com.uas.sso.SSOToken; import com.uas.sso.entity.register.SmsPersonalRegister; import com.uas.sso.core.Step; import com.uas.sso.core.Type; import com.uas.sso.core.PasswordStrength; import com.uas.sso.entity.App; import com.uas.sso.entity.Token; import com.uas.sso.entity.User; import com.uas.sso.entity.UserAccount; import com.uas.sso.foreign.entity.ForeignInfo; import com.uas.sso.logging.LoggerManager; import com.uas.sso.logging.RegisterBufferedLogger; import com.uas.sso.service.AppService; import com.uas.sso.service.PersonalAccountService; import com.uas.sso.service.UserService; import com.uas.sso.util.CaptchaUtil; import com.uas.sso.util.DomainUtil; import com.uas.sso.util.IpUtils; import com.uas.sso.util.MessageUtils; import com.uas.sso.util.PasswordLevelUtils; import com.uas.sso.util.StringUtil; import com.uas.sso.util.encry.Md5Utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.List; import java.util.Optional; import java.util.Random; /** * 个人注册controller * * @author uas * @date 2018/1/2 */ @RestController @RequestMapping("/sso/personal/register") public class PersonalRegisterController extends BaseController { @Autowired private UserService userService; @Autowired private PersonalAccountService personalAccountService; @Autowired private AppService appService; private RegisterBufferedLogger registerLogger = LoggerManager.getLogger(RegisterBufferedLogger.class); private final static Logger LOGGER = LoggerFactory.getLogger(PersonalRegisterController.class); /** * 验证码存session的可以 */ private static final String RESET_CAPTCHA = "resetCaptcha"; /** * 注册个人信息 * * @param user 用户信息(需要会员名,手机号,手机号所属区域,密码) * @param appId 注册应用标志 * @param code 验证码 * @param token 验证码tokenId * @return 成功:success(),失败:error("错误码", "错误信息") */ @RequestMapping(method = RequestMethod.POST) @ResponseBody public ModelMap register(User user, String appId, String code, String token, String baseUrl, String t, String returnUrl) throws UnsupportedEncodingException { // 获取参数 String vipName = user.getVipName(); String mobile = user.getMobile(); String mobileArea = user.getMobileArea(); String password = user.getPassword(); // 参数空校验 if (StringUtils.isEmpty(vipName)) { return error("会员名不能为空"); } if (StringUtils.isEmpty(password)) { return error("密码不能为空"); } if (StringUtils.isEmpty(mobile)) { return error("手机号不能为空"); } // 校验手机号 checkMobile(mobile, mobileArea); // 校验验证码 checkMobileCode(token, mobile, code); // 校验密码 if (PasswordStrength.WEAK.equals(PasswordLevelUtils.checkPasswordLevel(password))) { return error("密码须为8-20字符的英文、数字混合"); } // 设置第三方id if (!StringUtils.isEmpty(t)) { Token unionidToken = tokenService.findOne(t); Optional foreignInfo = Optional.ofNullable(unionidToken).map(value -> (ModelMap) unionidToken.getBind()).map(value -> (ForeignInfo) value.get("data")); if (!foreignInfo.isPresent()) { return error("参数错误,绑定失败"); } userService.setForeignOpenId(user, foreignInfo.get()); } // 注册并添加注册日志 appId = StringUtils.isEmpty(appId) ? "sso" : appId; user.setFromIp(IpUtils.getIp(request)); user.setFromUrl(URLDecoder.decode(returnUrl, "utf-8")); user = userService.register(user, appId); registerLogger.info(Type.REGISTER_PERSONAL.getValue(), Step.FIRST.getValue(), "个人注册成功", user, user.getFromApp()); // 注册成功后删除验证码token if (!StringUtils.isEmpty(t)) { tokenService.delete(t); } tokenService.delete(token); // 判断应用是否存在 App app = appService.findOne(appId); if (app == null) { LOGGER.warn("个人注册,应用{}不存在,注册用户:{}", appId, user.getUserUU()); return success(); } // 登录并返回数据 UserAccount userAccount = personalAccountService.findOneByUserUU(appId, user.getUserUU()); userAccount.setLastLoginTime(System.currentTimeMillis()); List loginUrls = appService.findAllLoginUrl(); SSOToken st = new SSOToken(request, userAccount.getMobile()); st.setData(JSON.toJSONString(userAccount)); SSOHelper.getSSOService().getConfig().setCookieDomain(DomainUtil.getFirstDomain(request)); SSOHelper.setSSOCookie(request, response, st, true); ModelMap data = new ModelMap(); data.addAttribute("data", userAccount) .addAttribute("loginUrls", loginUrls) .addAttribute("currentUrl", baseUrl); LOGGER.info("用户({})注册并登录成功,时间:{}", user.getUserUU(), System.currentTimeMillis()); return success(data); } @PostMapping("/sms") public ModelMap register(SmsPersonalRegister personalRegister) throws UnsupportedEncodingException { User user = new User(); String mobile = personalRegister.getMobile(); String password = getPassword(mobile.substring(mobile.length() - 3, mobile.length())); user.setVipName(mobile); user.setMobile(mobile); user.setPassword(password); ModelMap response = register(user, personalRegister.getAppId(), personalRegister.getCode(), personalRegister.getToken(), personalRegister.getBaseUrl(), personalRegister.getT(), personalRegister.getReturnUrl()); MessageUtils.sendSms("templateForSendSmsAfterRegisterSuccess", mobile, mobile, password); return response; } /** * 获取密码 * @param suffix 密码后缀 * @return */ private String getPassword(String suffix) { Random random = new Random(); String val = ""; // 生成4个字母 for (int i=0; i<3; i++) { int choice = random.nextInt(2) % 2 == 0 ? 65 : 97; val = val + (char)(choice + random.nextInt(26)); } // 3个数字 String number = random.nextInt(999) + 1000 + ""; number = number.substring(number.length() - 3, number.length()); val = val + number; // 后缀 val = val + suffix; return val; } /** * 获取验证码 * * @param mobile 手机号 * @param code 图片验证码 * @param sign 签名,签名不对不发送验证码 * @return success(tokenId) */ @RequestMapping(value = "/checkCode", method = RequestMethod.GET) @ResponseBody public ModelMap getCode(String mobile, String code, String sign) { // 参数校验 if (StringUtils.isEmpty(mobile)) { return error("请输入手机号"); } // 校验图片验证码 Token captchaToken = tokenService.findOne(request.getSession().getId()); if (captchaToken == null) { return error("图片验证码过期"); } if (code != null && !code.equalsIgnoreCase((String) captchaToken.getBind())) { return error("请输入正确的验证码"); } tokenService.delete(request.getSession().getId()); // 校验发送短信频率,60秒一次,key为#{sessionId}_#{类名} String key = request.getSession().getId() + "_" + this.getClass().getSimpleName(); Token rateToken = tokenService.findOne(key); if (rateToken != null) { return error("验证码发送间隔过快"); } // 获取验证码,根据签名判断是否需要获取验证码 String str = "{mobile=" + mobile + ",code=" + code + ",salt=sso}"; String existSign = Md5Utils.encode(str, null); String token; if (existSign.equals(sign)) { token = getMobileToken(mobile); } else { token = StringUtil.uuid(); LOGGER.warn("签名不通过!加密参数:{},sign:{}", str, sign); } // 设置发送短信频率 rateToken = new Token(key, "", 60); tokenService.save(rateToken); // 设置返回数据 ModelMap data = new ModelMap(); data.put("token", token); data.put("code", request.getSession().getAttribute("code")); request.getSession().setAttribute("token", token); return data; } /** * 校验验证码 * * @param code 验证码 * @param token 验证码tokenId * @return 验证成功:success(),验证失败:error("错误信息") */ @RequestMapping(value = "/checkCode", method = RequestMethod.POST) @ResponseBody public ModelMap checkCode(String token, String mobile, String code) { // 校验token是否正确 String sessionToken = (String) request.getSession().getAttribute("token"); if (StringUtils.isEmpty(sessionToken) || !sessionToken.equals(token)) { return error("请重新获取验证码"); } // 校验验证码 checkMobileCode(token, mobile, code); // 设置返回值 return success(); } }