package com.wechat.service; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.annotation.Resource; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.collections.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.alibaba.fastjson.JSONObject; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.Claim; import com.auth0.jwt.interfaces.DecodedJWT; import com.beust.jcommander.internal.Maps; import com.beust.jcommander.internal.Sets; import com.wechat.common.CommonHelper; import com.wechat.common.Constants; import com.wechat.common.utils.MailUtil; import com.wechat.common.utils.Md5Utils; import com.wechat.common.utils.StringsUtils; import com.wechat.dao.MdeCooperationMsgDao; import com.wechat.dao.MdeJobAdvertisedDao; import com.wechat.dao.MdeUserDao; import com.wechat.global.CustomException; import com.wechat.global.base.dao.RedisWithExpiryTimeDao; import com.wechat.global.message.InfoMsg; import com.wechat.model.dbEntity.MdeCooperationMsg; import com.wechat.model.dbEntity.MdeJobAdvertised; import com.wechat.model.dbEntity.MdeUser; import com.wechat.model.dto.AdImageDto; import com.wechat.model.dto.AuzUserInfoDto; import com.wechat.model.dto.LinkedInTokenDto; import com.wechat.model.dto.LinkedUserInfo; import com.wechat.model.requestDto.LoginByPasswordReq; import com.wechat.model.requestDto.LoginResp; import com.wechat.model.requestDto.PositionSearchReq; import com.wechat.model.requestDto.UserInfoDto; import com.wechat.model.requestDto.UserInfoWithOpenidDto; import com.wechat.model.responseDto.ResultEntity; @Service public class LoginService { @Resource private AuthorizedService authorizedService; @Autowired private CommonHelper commonHelper; @Autowired private MdeUserService mdeUserService; @Autowired private MdeWorkExperienceService mdeWorkExperienceService; // @Autowired // private RedisWithExpiryTimeDao captchaRedisDao; @Resource private CommonService commonService; @Autowired private MdeJobAdvertisedDao mdeJobAdvertisedDao; @Autowired private MdeCooperationMsgDao mdeCooperationMsgDao; @Autowired private RedisWithExpiryTimeDao redisWithExpiryTimeDao; @Autowired private MailUtil mailUtil; @Autowired private MdeUserDao mdeUserDao; private Logger log = LoggerFactory.getLogger(getClass()); @Value("#{configProperties['url.base']}") private String urlBase; @Value("#{configProperties['auditor_email_address']}") private String auditorEmail; /** * 用户登录 * @param req * @param resp * @param loginReq * @return */ public ResultEntity login(MdeUser mdeUser, LoginByPasswordReq loginReq, HttpServletResponse resp) { ResultEntity rest = new ResultEntity(); // 允许登录 0.允许 if (!"0".equals(mdeUser.getAllowFlag())) { return new ResultEntity<>(InfoMsg.ERROR_ILLEGAL_OPERATION_ERROR); } // 审核状态 2.通过 if (!"2".equals(mdeUser.getCheckStatus())) { return new ResultEntity<>(InfoMsg.ERROR_CHECKSTATUS_ERROR); } // 登录成功 String userCode = mdeUser.getUserCode(); //微信端静默登陆的情况下 绑定用户信息 String code = loginReq.getCode(); if(!StringsUtils.isEmpty(code)) { MdeUser bindingUser = new MdeUser(); bindingUser.setUserCode(userCode); //登录来源0.pc 1.移动端 //获取用户微信信息 AuzUserInfoDto auzUserInfoDto = authorizedService.getUserInfoDetail(code, "1"); bindingUser.setUnionId(auzUserInfoDto.getUnionid()); bindingUser.setOpenId(auzUserInfoDto.getOpenid()); //绑定 mdeUserService.bindInfo(bindingUser); } // 设置cookies commonService.setLoginCookies(resp,userCode,mdeUser.getIdentityFlag(),mdeUser.getCreateDate()); UserInfoDto userDto = new UserInfoDto(); try { commonService.addDomainUrlLogin(mdeUser); // 头像拼接域名 // 同名属性赋值 BeanUtils.copyProperties(userDto, mdeUser); } catch (Exception e) { log.error("*************登陆同名属性赋值出错************************",e); return new ResultEntity(InfoMsg.ERROR_LOGIN_MISS); } // 查询该用户的工作履历记录 int workExperienceCount = mdeWorkExperienceService.findByUserCodeCount(userCode); userDto.setWorkExperienceCount(workExperienceCount); rest.setResult(userDto); return rest; } /** * 验证用户登陆信息 * @param req * @param resp * @param loginReq * @return */ public ResultEntity checkPassword(LoginByPasswordReq loginReq) { ResultEntity rest = new ResultEntity(); //获取用户登陆信息 String userName = loginReq.getUserName(); String password = loginReq.getPassword(); // md5加密 password = Md5Utils.EncoderPassword(password); // 从redis中 获取登录密码错误记录 (5次尝试机会) String loginErrorKey = userName.toLowerCase(); int passwordErrorRecord = commonService.selectLoginPasswordErrorRecord(loginErrorKey); if (passwordErrorRecord >= 5) { rest.setMsg(InfoMsg.ERROR_LOGINPASSWORDERRORRECORD_ERROR); } else { // 查询该用户是否存在 MdeUser mdeUser = mdeUserService.findByUserName(userName); // 该用户不存在 if (mdeUser == null) { if(checkMail(userName)) { rest.setMsg(InfoMsg.ERROR_ENTERPRISE_USER_NOTEXIST); }else { rest.setMsg(InfoMsg.ERROR_PERSON_USER_NOTEXIST); } } else { // 用户名和密码不一致 if (!password.equals(mdeUser.getPassword())) { passwordErrorRecord += 1; // 密码错误次数存入redis commonService.insertLoginPasswordRecord(loginErrorKey, String.valueOf(passwordErrorRecord)); if (passwordErrorRecord == 2) { rest.setMsg(InfoMsg.EERROE_SURPLUSCOUNT_ERROR); } else { rest.setMsg(InfoMsg.ERROR_LOGIN); } } else { // 清缓存 redis redisWithExpiryTimeDao.delete("passwordErrorRecord" + loginErrorKey); } rest.setResult(mdeUser); } } return rest; } /** * 邮箱验证 * * @param userName * @return */ public boolean checkMail(String mail) { boolean flag = false; try { String check = "^([a-z0-9A-Z]+[-|_|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$"; Pattern regex = Pattern.compile(check); Matcher matcher = regex.matcher(mail); flag = matcher.matches(); } catch (Exception e) { log.info(e.getMessage()); return flag; } return flag; } /** *领英第三方登录 * * @param userName * @return */ public ResultEntity loginByLinkedInCode(HttpServletRequest request, HttpServletResponse response, String code) throws Exception { UserInfoWithOpenidDto userDto = new UserInfoWithOpenidDto(); // 获取令牌 access_token LinkedInTokenDto linkedInTokenDto = authorizedService.getLinkedInTokenDto(code); if (linkedInTokenDto == null) { return new ResultEntity(InfoMsg.ERROR_AUZ_FAILED); } // 根据access_token 获取用户信息 LinkedUserInfo linkedUserInfo = authorizedService.getLinkedUserInfo(linkedInTokenDto); if (linkedUserInfo == null) { return new ResultEntity(InfoMsg.ERROR_AUZ_FAILED); } // 根据linkedId查询用户 MdeUser mdeUser = mdeUserService.findByLinkedId(linkedUserInfo.getId()); if (mdeUser != null) { // 允许登录 0.允许 if (!"0".equals(mdeUser.getAllowFlag())) { return new ResultEntity<>(InfoMsg.ERROR_ILLEGAL_OPERATION_ERROR); } // 审核状态 2.通过 if (!"2".equals(mdeUser.getCheckStatus())) { return new ResultEntity<>(InfoMsg.ERROR_CHECKSTATUS_ERROR); } String userCode = mdeUser.getUserCode(); // 设置cookies commonService.setLoginCookies(response,userCode,mdeUser.getIdentityFlag(),mdeUser.getCreateDate()); // 头像拼接域名 commonService.addDomainUrlLogin(mdeUser); //相同属性复制 BeanUtils.copyProperties(userDto, mdeUser); //清除敏感信息 userDto.cleanInfo(); // 查询该用户的工作履历记录 int workExperienceCount = mdeWorkExperienceService.findByUserCodeCount(userCode); userDto.setWorkExperienceCount(workExperienceCount); //记录登陆历史 commonService.addLoginHis(request,userCode); return new ResultEntity(InfoMsg.SUCCESS_REQUEST, userDto); } else { userDto.setLinkedInId(linkedUserInfo.getId()); // code=1 跳到绑定页面 return new ResultEntity<>(InfoMsg.ERROR_BINDING_ERROR, userDto); } } /** *微信第三方登录 * * @param userName * @return */ public ResultEntity loginByWechatCode(HttpServletRequest request, HttpServletResponse response, String code, String loginModel) { ResultEntity restEnty = new ResultEntity(); UserInfoWithOpenidDto userDto = new UserInfoWithOpenidDto(); AuzUserInfoDto auzUserInfoDto = authorizedService.getUserInfoDetail(code, loginModel); if (auzUserInfoDto == null) { restEnty.setMsg(InfoMsg.ERROR_AUZ_FAILED); } else { // 根据UnionId查询用户 MdeUser mdeUser = mdeUserService.findByUnionId(auzUserInfoDto.getUnionid()); //微信登陆共通处理 restEnty = loginByWechatBase(response,auzUserInfoDto.getUnionid(),auzUserInfoDto.getOpenid(),"",loginModel,mdeUser); if (InfoMsg.SUCCESS_REQUEST.getCode().equals(restEnty.getCode())) { //正常处理的场合 userDto = restEnty.getResult(); //记录登陆历史 commonService.addLoginHis(request,userDto.getUserCode()); } else if(InfoMsg.ERROR_BINDING_ERROR.getCode().equals(restEnty.getCode())){ //未绑定的情况下 userDto.setCity(auzUserInfoDto.getCity()); userDto.setCountry(auzUserInfoDto.getCountry()); userDto.setProvince(auzUserInfoDto.getProvince()); userDto.setWechHeadImage(auzUserInfoDto.getHeadimgurl()); userDto.setUnionid(auzUserInfoDto.getUnionid()); if ("1".equals(loginModel)) { // 手机端登录 userDto.setOpenId(auzUserInfoDto.getOpenid()); // 手机端登录存储 (微信模板信息推送需要) } restEnty.setResult(userDto); } } return restEnty; } /** *微信第三方登录 基础处理 * * @param loginModel 1:移动端 0:PC端 * @return */ public ResultEntity loginByWechatBase(HttpServletResponse response, String unionId, String openid, String miniOpenid,String loginModel,MdeUser mdeUser) { ResultEntity restEnty = new ResultEntity(); if (mdeUser != null) { // 允许登录 0.允许 if (!"0".equals(mdeUser.getAllowFlag())) { restEnty.setMsg(InfoMsg.ERROR_ILLEGAL_OPERATION_ERROR); } else if (!"2".equals(mdeUser.getCheckStatus())) { // 审核状态 2.通过 restEnty.setMsg(InfoMsg.ERROR_CHECKSTATUS_ERROR); } else { UserInfoWithOpenidDto userDto = new UserInfoWithOpenidDto(); String userCode = mdeUser.getUserCode(); // 设置cookies commonService.setLoginCookies(response,userCode,mdeUser.getIdentityFlag(),mdeUser.getCreateDate()); try { // 头像拼接域名 commonService.addDomainUrlLogin(mdeUser); //相同属性copy BeanUtils.copyProperties(userDto, mdeUser); //清除敏感信息 userDto.cleanInfo(); } catch (Exception e) { log.info(e.getMessage()); } // 移动端 更新openId if (loginModel.equals("1")) { // 绑定信息 if (!StringsUtils.isEmpty(unionId)) { //微信登陆,去除领英影响 mdeUser.setLinkedinId(null); mdeUser.setUnionId(unionId); mdeUser.setOpenId(openid); mdeUser.setOpenIdMini(miniOpenid); mdeUserService.bindInfo(mdeUser); } } // 查询该用户的工作履历记录 int workExperienceCount = mdeWorkExperienceService.findByUserCodeCount(userCode); userDto.setWorkExperienceCount(workExperienceCount); restEnty.setResult(userDto); } } else { //未绑定 restEnty.setMsg(InfoMsg.ERROR_BINDING_ERROR); } return restEnty; } // 解除微信第三方登录 public ResultEntity unBindingWechatCode(String code, String loginModel) { AuzUserInfoDto auzUserInfoDto = authorizedService.getUserInfoDetail(code, loginModel); if (auzUserInfoDto == null) { return new ResultEntity(InfoMsg.ERROR_AUZ_FAILED); } else { UserInfoWithOpenidDto userDto = new UserInfoWithOpenidDto(); userDto.setCity(auzUserInfoDto.getCity()); userDto.setCountry(auzUserInfoDto.getCountry()); userDto.setProvince(auzUserInfoDto.getProvince()); userDto.setWechHeadImage(auzUserInfoDto.getHeadimgurl()); userDto.setUnionid(auzUserInfoDto.getUnionid()); if (loginModel.equals("1")) { // 手机端登录 userDto.setOpenId(auzUserInfoDto.getOpenid()); // 手机端登录存储 (微信模板信息推送需要) } return new ResultEntity<>(InfoMsg.SUCCESS_REQUEST, userDto); } } /** * 绑定账号 * * @param req * @param resp * @param jo * @return */ @Transactional public ResultEntity binDingAccount(HttpServletRequest req, HttpServletResponse resp, JSONObject jo) { if (StringsUtils.isEmpty(jo.getString("type"))) { return new ResultEntity(InfoMsg.ERROR_Type_MISS); } String userName = jo.getString("userName"); String password = jo.getString("password"); if (StringsUtils.isEmpty(userName) || StringsUtils.isEmpty(password)) { return new ResultEntity(InfoMsg.ERROR_LOGIN); } MdeUser mdeUser = mdeUserService.findByUserName(userName); // 判断用户名是否存在 if (mdeUser == null) { if(checkMail(userName)) { return new ResultEntity(InfoMsg.ERROR_ENTERPRISE_USER_NOTEXIST); }else { return new ResultEntity(InfoMsg.ERROR_PERSON_USER_NOTEXIST); } } // md5 加密 password = Md5Utils.EncoderPassword(password); // 比较密码是否相同,否则绑定失败 if (!mdeUser.getPassword().equals(password)) { return new ResultEntity(InfoMsg.ERROR_LOGIN); } String loginRestJson = jo.getString("result"); if (StringsUtils.isEmpty(loginRestJson)) { return new ResultEntity<>(InfoMsg.ERROR_PARAMS_ERROR); } LoginResp loginResp = JSONObject.parseObject(loginRestJson, LoginResp.class); String userCode = mdeUser.getUserCode(); if ("0".equals(jo.getString("type"))) { if (StringsUtils.isEmpty(loginResp.getUnionId())) { return new ResultEntity(InfoMsg.ERROR_PARAMS_ERROR); } // 获取第三方用户信息 mdeUser.setOpenId(StringsUtils.isEmpty(loginResp.getOpenId()) ? "" : loginResp.getOpenId()); mdeUser.setUnionId(loginResp.getUnionId()); //微信登陆,去除领英影响 mdeUser.setLinkedinId(null); mdeUserService.bindInfo(mdeUser); } else { // 参数验证 if (StringsUtils.isEmpty(loginResp.getLinkedInId())) { return new ResultEntity(InfoMsg.ERROR_PARAMS_ERROR); } // 先解绑领英 // 去除微信影响 mdeUser.setUnionId(null); mdeUserService.unbind(mdeUser); // 领英绑定 mdeUser.setLinkedinId(loginResp.getLinkedInId()); mdeUserService.update(mdeUser); } // 查询该用户的工作履历记录 int workExperienceCount = mdeWorkExperienceService.findByUserCodeCount(mdeUser.getUserCode()); UserInfoDto userDto = new UserInfoDto(); try { // 头像拼接域名 commonService.addDomainUrlLogin(mdeUser); // 同名属性赋值 BeanUtils.copyProperties(userDto, mdeUser); } catch (Exception e) { log.info(e.getMessage()); } userDto.setWorkExperienceCount(workExperienceCount); // 设置cookies commonService.setLoginCookies(resp,userCode,mdeUser.getIdentityFlag(),mdeUser.getCreateDate()); //记录登陆历史 commonService.addLoginHis(req,userCode); return new ResultEntity(InfoMsg.SUCCESS_REQUEST, userDto); } /** * 职位检索 * * @param searchReq * @return */ public ResultEntity> searchJob(PositionSearchReq searchReq) { // 搜索关键词为空 返回空分页对象 Map maps = Maps.newHashMap(); List list = null; if (StringsUtils.isEmpty(searchReq.getKeyWord())) { return new ResultEntity<>(InfoMsg.SUCCESS_REQUEST); } // 拆分关键词 // Map param = keyWordSplit(searchReq.getKeyWord()); Map param = new HashMap<>(1); param.put("keyWord",searchReq.getKeyWord()); list = mdeJobAdvertisedDao.searchJobNotLogin(param); // 隐藏酒店名称前三位 // List mdeJobAdvertisedList = // hideHotelName(searchJob.getResultList()); // searchJob.setResultList(mdeJobAdvertisedList); maps.put("page", list); maps.put("recommentHotels", commonService.getNotLoginRecommentHotels()); // 推荐酒店 maps.put("recommentJobs", commonService.getNotLoginRecommentJobs()); return new ResultEntity<>(InfoMsg.SUCCESS_REQUEST, maps); } /** * 合作伙伴 * * @param mdeCooperationMsg * @param lang * @return */ @Transactional public InfoMsg cooperate(MdeCooperationMsg mdeCooperationMsg, String lang) { try { mdeCooperationMsgDao.insert(mdeCooperationMsg); String message = "有媒体/合作伙伴【"+mdeCooperationMsg.getCompanyName()+"】给您留下了信息,请您查看!"; commonService.sendNoticeEmail(message, commonService.getNoticeEmailAdds(),"媒体/合作伙伴"); } catch (Exception e) { log.info("新增合作伙伴失败" + e.getMessage()); throw new CustomException(InfoMsg.ERROR_INSERT_ERROR); } return InfoMsg.SUCCESS_REQUEST; } /** * 企业用户 邮箱激活认证 * * @param activationToken * @param userCode * @return */ @Transactional(readOnly = false) public void activationEnterprise(String activationToken, String userCode, HttpServletResponse resp) { String messageCn = ""; // 中文 String messageEn = ""; // 英文 String token = redisWithExpiryTimeDao.select(activationToken); if (StringsUtils.isEmpty(userCode) || StringsUtils.isEmpty(activationToken)) { messageCn = "验证失败,请重新验证或发送邮件联系我们!"; messageEn = "Verification failed. Please try again or drop an email to us."; } else if (StringsUtils.isEmpty(token)) { messageCn = "验证信息已过期,请重新注册!"; messageEn = "Verification is expired. Please try again."; } else { // token 非法 return DecodedJWT jwt; try { JWTVerifier verifier = JWT.require(Algorithm.HMAC512(Constants.TOKEN_KEY)).build(); jwt = verifier.verify(activationToken); Map map = jwt.getClaims(); String hiddenUserCode = map.get(Constants.ACTIVATION_TOKEN).asString(); // 验证token是否被篡改 if (StringsUtils.isEqual(userCode, hiddenUserCode)) { MdeUser mdeUser = mdeUserDao.getInfoById(userCode); // 增加用户状态判断 为待激活 if(mdeUser.getCheckStatus().equals("4")) { mdeUser.setUserCode(userCode); mdeUser.setCheckStatus("1"); // 待审核 mdeUser.setUpdateDate(new Date()); // 更新企业审核状态 mdeUserService.update(mdeUser); // 链接 过期时间5天 redisWithExpiryTimeDao.insertDay(activationToken, "true", 5); messageCn = "验证通过,请等待人工审核!";// Verification passed. Please wait for the manual check. messageEn = "Verification passed. Please wait for the manual check."; // 通知邮件, 验证通过后发送给 管理人员 StringBuffer buf = new StringBuffer("企业用户:"); buf.append(mdeUser.getName()); buf.append(",注册邮箱:" + mdeUser.getUserName()); buf.append(",联系人:" + mdeUser.getEntContacts()); buf.append(",联系方式:" + mdeUser.getEntPhone()); buf.append(",激活完成待审核!"); mailUtil.sendCodeMail(buf.toString(), auditorEmail); // 企业激活成功 发送邮件通知管理人员 commonService.sendNoticeEmail(buf.toString(), commonService.getNoticeEmailAdds(),"新企业用户已经完成注册"); }else { messageCn = "验证已通过";// Verification passed. Please wait for the manual check. messageEn = "Verification passed."; } } else { messageCn = "验证失败,请重新验证或发送邮件联系我们!"; messageEn = "Verification failed. Please try again or drop an email to us."; } } catch (Exception exception) { messageCn = "验证失败,请重新验证或发送邮件联系我们!"; messageEn = "Verification failed. Please try again or drop an email to us."; } } try { String cncode = URLEncoder.encode(messageCn, "utf-8"); Cookie cookieCn = new Cookie("messageCn", cncode); cookieCn.setPath("/"); resp.addCookie(cookieCn); String encode = URLEncoder.encode(messageEn, "utf-8");// 不使用该编码,会出现 java.lang.IllegalArgumentException: An invalid character [32] was present in the Cookie value Cookie cookieEn = new Cookie("messageEn", encode); cookieEn.setPath("/"); resp.addCookie(cookieEn); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } public ResultEntity> getLoginInitImage(String type) { if (StringsUtils.isEmpty(type)) { return new ResultEntity<>(InfoMsg.ERROR_TYPE_ERROR); } Map maps = Maps.newHashMap(); List adImage = commonService.getAdImages(Constants.PC_LOGIN_BROADCAST); // 登录页广告 轮播图 AdImageDto backImage = null; if (type.equals("0")) { // pc List adImages = commonService.getAdImages(Constants.PC_LOGIN_BG); // pc登录背景图 if (CollectionUtils.isNotEmpty(adImages)) { backImage = adImages.get(0); } } else if (type.equals("1")) { // 手机端 List adImages = commonService.getAdImages(Constants.SJ_LOGIN_BG); // 手机登录背景图 backImage = adImages.get(0); } maps.put("adImage", adImage); if (backImage != null) { maps.put("backImage", backImage.getImageUrl()); } else { maps.put("backImage", ""); } return new ResultEntity<>(InfoMsg.SUCCESS_REQUEST, maps); } /** * 关键词拆分 * * @param keyWord * @return */ private Map keyWordSplit(String keyWord) { Map map = Maps.newHashMap(); Set set = Sets.newHashSet(); List split = Arrays.asList(keyWord.trim().split(" ")); if (CollectionUtils.isEmpty(split)) { map.put("keyWord", keyWord); } else { for (String string : split) { set.add(string); } map.put("keyWord", set); } return map; } /** * 隐藏酒店名称(前三位*) * * @param list * @return */ // private List hideHotelName(List list) { // for (MdeJobAdvertised mdeJobAdvertised : list) { // String publisherName = mdeJobAdvertised.getPublisherName(); // if (StringsUtils.isNotEmpty(publisherName)) { // if (publisherName.trim().length()>=3) { // mdeJobAdvertised.setPublisherName(publisherName.replace(publisherName.substring(0, // 3), "***"));; // } else if (publisherName.trim().length()==2) { // mdeJobAdvertised.setPublisherName(publisherName.replace(publisherName.substring(0, // 2), "**"));; // } else if (publisherName.trim().length()==1) { // mdeJobAdvertised.setPublisherName(publisherName.replace(publisherName.substring(0, // 1), "*"));; // } else { // mdeJobAdvertised.setPublisherName(publisherName); // } // } // } // return list; // } }