package org.jeecg.modules.system.controller; import cn.hutool.core.util.RandomUtil; import com.alibaba.fastjson.JSONObject; import com.aliyuncs.exceptions.ClientException; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.IdWorker; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authz.annotation.RequiresRoles; import org.jeecg.common.api.vo.Result; import org.jeecg.common.constant.CacheConstant; import org.jeecg.common.constant.CommonConstant; import org.jeecg.common.constant.SymbolConstant; import org.jeecg.common.system.util.JwtUtil; import org.jeecg.common.system.vo.LoginUser; import org.jeecg.common.util.*; import org.jeecg.common.util.encryption.EncryptedString; import org.jeecg.config.JeecgBaseConfig; import org.jeecg.modules.base.service.BaseCommonService; import org.jeecg.modules.system.entity.SysDepart; import org.jeecg.modules.system.entity.SysRoleIndex; import org.jeecg.modules.system.entity.SysTenant; import org.jeecg.modules.system.entity.SysUser; import org.jeecg.modules.system.model.SysLoginModel; import org.jeecg.modules.system.service.*; import org.jeecg.modules.system.service.impl.SysBaseApiImpl; import org.jeecg.modules.system.util.RandImageUtil; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.*; /** * @Author scott * @since 2018-12-17 */ @RestController @RequestMapping("/sys") @Api(tags="用户登录") @Slf4j public class LoginController { @Autowired private ISysUserService sysUserService; @Autowired private ISysPermissionService sysPermissionService; @Autowired private SysBaseApiImpl sysBaseApi; @Autowired private ISysLogService logService; @Autowired private RedisUtil redisUtil; @Autowired private ISysDepartService sysDepartService; @Autowired private ISysTenantService sysTenantService; @Autowired private ISysDictService sysDictService; @Resource private BaseCommonService baseCommonService; @Autowired private JeecgBaseConfig jeecgBaseConfig; private final String BASE_CHECK_CODES = "qwertyuiplkjhgfdsazxcvbnmQWERTYUPLKJHGFDSAZXCVBNM1234567890"; @ApiOperation("登录接口") @RequestMapping(value = "/login", method = RequestMethod.POST) public Result login(@RequestBody SysLoginModel sysLoginModel){ Result result = new Result(); String username = sysLoginModel.getUsername(); String password = sysLoginModel.getPassword(); //update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户 if(isLoginFailOvertimes(username)){ return result.error500("该用户登录失败次数过多,请于10分钟后再次登录!"); } //update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户 //update-begin--Author:scott Date:20190805 for:暂时注释掉密码加密逻辑,有点问题 //前端密码加密,后端进行密码解密 //password = AesEncryptUtil.desEncrypt(sysLoginModel.getPassword().replaceAll("%2B", "\\+")).trim();//密码解密 //update-begin--Author:scott Date:20190805 for:暂时注释掉密码加密逻辑,有点问题 //update-begin-author:taoyan date:20190828 for:校验验证码 // String captcha = sysLoginModel.getCaptcha(); // if(captcha==null){ // result.error500("验证码无效"); // return result; // } // String lowerCaseCaptcha = captcha.toLowerCase(); //update-begin-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906 // 加入密钥作为混淆,避免简单的拼接,被外部利用,用户自定义该密钥即可 String origin = sysLoginModel.getCheckKey()+jeecgBaseConfig.getSignatureSecret(); String realKey = Md5Util.md5Encode(origin, "utf-8"); //update-end-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906 Object checkCode = redisUtil.get(realKey); //当进入登录页时,有一定几率出现验证码错误 #1714 // if(checkCode==null || !checkCode.toString().equals(lowerCaseCaptcha)) { // log.warn("验证码错误,key= {} , Ui checkCode= {}, Redis checkCode = {}", sysLoginModel.getCheckKey(), lowerCaseCaptcha, checkCode); // result.error500("验证码错误"); // // 改成特殊的code 便于前端判断 // result.setCode(HttpStatus.PRECONDITION_FAILED.value()); // return result; // } //update-end-author:taoyan date:20190828 for:校验验证码 //1. 校验用户是否有效 //update-begin-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug,if条件永远为false LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(SysUser::getUsername,username); SysUser sysUser = sysUserService.getOne(queryWrapper); //update-end-author:wangshuai date:20200601 for: 登录代码验证用户是否注销bug,if条件永远为false result = sysUserService.checkUserIsEffective(sysUser); if(!result.isSuccess()) { return result; } //2. 校验用户名或密码是否正确 String userpassword = PasswordUtil.encrypt(username, password, sysUser.getSalt()); String syspassword = sysUser.getPassword(); if (!syspassword.equals(userpassword)) { //update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户 addLoginFailOvertimes(username); //update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户 result.error500("用户名或密码错误"); return result; } //用户登录信息 userInfo(sysUser, result); //update-begin--Author:liusq Date:20210126 for:登录成功,删除redis中的验证码 redisUtil.del(realKey); //update-begin--Author:liusq Date:20210126 for:登录成功,删除redis中的验证码 redisUtil.del(CommonConstant.LOGIN_FAIL + username); LoginUser loginUser = new LoginUser(); BeanUtils.copyProperties(sysUser, loginUser); baseCommonService.addLog("用户名: " + username + ",登录成功!", CommonConstant.LOG_TYPE_1, null,loginUser); //update-end--Author:wangshuai Date:20200714 for:登录日志没有记录人员 return result; } /** * 【vue3专用】获取用户信息 */ @GetMapping("/user/getUserInfo") public Result getUserInfo(HttpServletRequest request){ Result result = new Result(); String username = JwtUtil.getUserNameByToken(request); if(oConvertUtils.isNotEmpty(username)) { // 根据用户名查询用户信息 SysUser sysUser = sysUserService.getUserByName(username); JSONObject obj=new JSONObject(); //update-begin---author:scott ---date:2022-06-20 for:vue3前端,支持自定义首页----------- String version = request.getHeader(CommonConstant.VERSION); //update-begin---author:liusq ---date:2022-06-29 for:接口返回值修改,同步修改这里的判断逻辑----------- SysRoleIndex roleIndex = sysUserService.getDynamicIndexByUserRole(username, version); if (oConvertUtils.isNotEmpty(version) && roleIndex != null && oConvertUtils.isNotEmpty(roleIndex.getUrl())) { String homePath = roleIndex.getUrl(); if (!homePath.startsWith(SymbolConstant.SINGLE_SLASH)) { homePath = SymbolConstant.SINGLE_SLASH + homePath; } sysUser.setHomePath(homePath); } //update-begin---author:liusq ---date:2022-06-29 for:接口返回值修改,同步修改这里的判断逻辑----------- //update-end---author:scott ---date::2022-06-20 for:vue3前端,支持自定义首页-------------- obj.put("userInfo",sysUser); obj.put("sysAllDictItems", sysDictService.queryAllDictItems()); result.setResult(obj); result.success(""); } return result; } /** * 退出登录 * @param request * @param response * @return */ @RequestMapping(value = "/logout") public Result logout(HttpServletRequest request,HttpServletResponse response) { //用户退出逻辑 String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN); if(oConvertUtils.isEmpty(token)) { return Result.error("退出登录失败!"); } String username = JwtUtil.getUsername(token); LoginUser sysUser = sysBaseApi.getUserByName(username); if(sysUser!=null) { //update-begin--Author:wangshuai Date:20200714 for:登出日志没有记录人员 baseCommonService.addLog("用户名: "+sysUser.getRealname()+",退出成功!", CommonConstant.LOG_TYPE_1, null,sysUser); //update-end--Author:wangshuai Date:20200714 for:登出日志没有记录人员 log.info(" 用户名: "+sysUser.getRealname()+",退出成功! "); //清空用户登录Token缓存 redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token); //清空用户登录Shiro权限缓存 redisUtil.del(CommonConstant.PREFIX_USER_SHIRO_CACHE + sysUser.getId()); //清空用户的缓存信息(包括部门信息),例如sys:cache:user:: redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_CACHE, sysUser.getUsername())); //调用shiro的logout SecurityUtils.getSubject().logout(); return Result.ok("退出登录成功!"); }else { return Result.error("Token无效!"); } } /** * 获取访问量 * @return */ @GetMapping("loginfo") public Result loginfo() { Result result = new Result(); JSONObject obj = new JSONObject(); //update-begin--Author:zhangweijian Date:20190428 for:传入开始时间,结束时间参数 // 获取一天的开始和结束时间 Calendar calendar = new GregorianCalendar(); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); Date dayStart = calendar.getTime(); calendar.add(Calendar.DATE, 1); Date dayEnd = calendar.getTime(); // 获取系统访问记录 Long totalVisitCount = logService.findTotalVisitCount(); obj.put("totalVisitCount", totalVisitCount); Long todayVisitCount = logService.findTodayVisitCount(dayStart,dayEnd); obj.put("todayVisitCount", todayVisitCount); Long todayIp = logService.findTodayIp(dayStart,dayEnd); //update-end--Author:zhangweijian Date:20190428 for:传入开始时间,结束时间参数 obj.put("todayIp", todayIp); result.setResult(obj); result.success("登录成功"); return result; } /** * 获取访问量 * @return */ @GetMapping("visitInfo") public Result>> visitInfo() { Result>> result = new Result>>(); Calendar calendar = new GregorianCalendar(); calendar.set(Calendar.HOUR_OF_DAY,0); calendar.set(Calendar.MINUTE,0); calendar.set(Calendar.SECOND,0); calendar.set(Calendar.MILLISECOND,0); calendar.add(Calendar.DAY_OF_MONTH, 1); Date dayEnd = calendar.getTime(); calendar.add(Calendar.DAY_OF_MONTH, -7); Date dayStart = calendar.getTime(); List> list = logService.findVisitCount(dayStart, dayEnd); result.setResult(oConvertUtils.toLowerCasePageList(list)); return result; } /** * 登陆成功选择用户当前部门 * @param user * @return */ @RequestMapping(value = "/selectDepart", method = RequestMethod.PUT) public Result selectDepart(@RequestBody SysUser user) { Result result = new Result(); String username = user.getUsername(); if(oConvertUtils.isEmpty(username)) { LoginUser sysUser = (LoginUser)SecurityUtils.getSubject().getPrincipal(); username = sysUser.getUsername(); } //获取登录部门 String orgCode= user.getOrgCode(); //获取登录租户 Integer tenantId = user.getLoginTenantId(); this.sysUserService.updateUserDepart(username, orgCode,tenantId); SysUser sysUser = sysUserService.getUserByName(username); JSONObject obj = new JSONObject(); obj.put("userInfo", sysUser); result.setResult(obj); return result; } /** * 短信登录接口 * * @param jsonObject * @return */ @PostMapping(value = "/sms") public Result sms(@RequestBody JSONObject jsonObject) { Result result = new Result(); String mobile = jsonObject.get("mobile").toString(); //手机号模式 登录模式: "2" 注册模式: "1" String smsmode=jsonObject.get("smsmode").toString(); log.info(mobile); if(oConvertUtils.isEmpty(mobile)){ result.setMessage("手机号不允许为空!"); result.setSuccess(false); return result; } //update-begin-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906 String redisKey = CommonConstant.PHONE_REDIS_KEY_PRE+mobile; Object object = redisUtil.get(redisKey); //update-end-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906 if (object != null) { result.setMessage("验证码10分钟内,仍然有效!"); result.setSuccess(false); return result; } //随机数 String captcha = RandomUtil.randomNumbers(6); JSONObject obj = new JSONObject(); obj.put("code", captcha); try { boolean b = false; //注册模板 if (CommonConstant.SMS_TPL_TYPE_1.equals(smsmode)) { SysUser sysUser = sysUserService.getUserByPhone(mobile); if(sysUser!=null) { result.error500(" 手机号已经注册,请直接登录!"); baseCommonService.addLog("手机号已经注册,请直接登录!", CommonConstant.LOG_TYPE_1, null); return result; } b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.REGISTER_TEMPLATE_CODE); }else { //登录模式,校验用户有效性 SysUser sysUser = sysUserService.getUserByPhone(mobile); result = sysUserService.checkUserIsEffective(sysUser); if(!result.isSuccess()) { String message = result.getMessage(); String userNotExist="该用户不存在,请注册"; if(userNotExist.equals(message)){ result.error500("该用户不存在或未绑定手机号"); } return result; } /** * smsmode 短信模板方式 0 .登录模板、1.注册模板、2.忘记密码模板 */ if (CommonConstant.SMS_TPL_TYPE_0.equals(smsmode)) { //登录模板 b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.LOGIN_TEMPLATE_CODE); } else if(CommonConstant.SMS_TPL_TYPE_2.equals(smsmode)) { //忘记密码模板 b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.FORGET_PASSWORD_TEMPLATE_CODE); } } if (b == false) { result.setMessage("短信验证码发送失败,请稍后重试"); result.setSuccess(false); return result; } //update-begin-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906 //验证码10分钟内有效 redisUtil.set(redisKey, captcha, 600); //update-end-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906 //update-begin--Author:scott Date:20190812 for:issues#391 //result.setResult(captcha); //update-end--Author:scott Date:20190812 for:issues#391 result.setSuccess(true); } catch (ClientException e) { e.printStackTrace(); result.error500(" 短信接口未配置,请联系管理员!"); return result; } return result; } /** * 手机号登录接口 * * @param jsonObject * @return */ @ApiOperation("手机号登录接口") @PostMapping("/phoneLogin") public Result phoneLogin(@RequestBody JSONObject jsonObject) { Result result = new Result(); String phone = jsonObject.getString("mobile"); //update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户 if(isLoginFailOvertimes(phone)){ return result.error500("该用户登录失败次数过多,请于10分钟后再次登录!"); } //update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户 //校验用户有效性 SysUser sysUser = sysUserService.getUserByPhone(phone); result = sysUserService.checkUserIsEffective(sysUser); if(!result.isSuccess()) { return result; } String smscode = jsonObject.getString("captcha"); //update-begin-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906 String redisKey = CommonConstant.PHONE_REDIS_KEY_PRE+phone; Object code = redisUtil.get(redisKey); //update-end-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906 if (!smscode.equals(code)) { //update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户 addLoginFailOvertimes(phone); //update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户 result.setMessage("手机验证码错误"); return result; } //用户信息 userInfo(sysUser, result); //添加日志 baseCommonService.addLog("用户名: " + sysUser.getUsername() + ",登录成功!", CommonConstant.LOG_TYPE_1, null); return result; } /** * 用户信息 * * @param sysUser * @param result * @return */ private Result userInfo(SysUser sysUser, Result result) { String username = sysUser.getUsername(); String syspassword = sysUser.getPassword(); // 获取用户部门信息 JSONObject obj = new JSONObject(new LinkedHashMap<>()); //1.生成token String token = JwtUtil.sign(username, syspassword); // 设置token缓存有效时间 redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token); redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 2 / 1000); obj.put("token", token); //2.设置登录租户 Result loginTenantError = sysUserService.setLoginTenant(sysUser, obj, username,result); if (loginTenantError != null) { return loginTenantError; } //3.设置登录用户信息 obj.put("userInfo", sysUser); //4.设置登录部门 List departs = sysDepartService.queryUserDeparts(sysUser.getId()); obj.put("departs", departs); if (departs == null || departs.size() == 0) { obj.put("multi_depart", 0); } else if (departs.size() == 1) { sysUserService.updateUserDepart(username, departs.get(0).getOrgCode(),null); obj.put("multi_depart", 1); } else { //查询当前是否有登录部门 // update-begin--Author:wangshuai Date:20200805 for:如果用戶为选择部门,数据库为存在上一次登录部门,则取一条存进去 SysUser sysUserById = sysUserService.getById(sysUser.getId()); if(oConvertUtils.isEmpty(sysUserById.getOrgCode())){ sysUserService.updateUserDepart(username, departs.get(0).getOrgCode(),null); } // update-end--Author:wangshuai Date:20200805 for:如果用戶为选择部门,数据库为存在上一次登录部门,则取一条存进去 obj.put("multi_depart", 2); } obj.put("sysAllDictItems", sysDictService.queryAllDictItems()); result.setResult(obj); result.success("登录成功"); return result; } /** * 获取加密字符串 * @return */ @GetMapping(value = "/getEncryptedString") public Result> getEncryptedString(){ Result> result = new Result>(); Map map = new HashMap(5); map.put("key", EncryptedString.key); map.put("iv",EncryptedString.iv); result.setResult(map); return result; } /** * 后台生成图形验证码 :有效 * @param response * @param key */ @ApiOperation("获取验证码") @GetMapping(value = "/randomImage/{key}") public Result randomImage(HttpServletResponse response,@PathVariable("key") String key){ Result res = new Result(); try { //生成验证码 String code = RandomUtil.randomString(BASE_CHECK_CODES,4); //存到redis中 String lowerCaseCode = code.toLowerCase(); //update-begin-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906 // 加入密钥作为混淆,避免简单的拼接,被外部利用,用户自定义该密钥即可 String origin = lowerCaseCode+key+jeecgBaseConfig.getSignatureSecret(); String realKey = Md5Util.md5Encode(origin, "utf-8"); //update-end-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906 redisUtil.set(realKey, lowerCaseCode, 60); log.info("获取验证码,Redis key = {},checkCode = {}", realKey, code); //返回前端 String base64 = RandImageUtil.generate(code); res.setSuccess(true); res.setResult(base64); } catch (Exception e) { log.error(e.getMessage(), e); res.error500("获取验证码失败,请检查redis配置!"); return res; } return res; } /** * 切换菜单表为vue3的表 */ @RequiresRoles({"admin"}) @GetMapping(value = "/switchVue3Menu") public Result switchVue3Menu(HttpServletResponse response) { Result res = new Result(); sysPermissionService.switchVue3Menu(); return res; } /** * app登录 * @param sysLoginModel * @return * @throws Exception */ @RequestMapping(value = "/mLogin", method = RequestMethod.POST) public Result mLogin(@RequestBody SysLoginModel sysLoginModel) throws Exception { Result result = new Result(); String username = sysLoginModel.getUsername(); String password = sysLoginModel.getPassword(); JSONObject obj = new JSONObject(); //update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户 if(isLoginFailOvertimes(username)){ return result.error500("该用户登录失败次数过多,请于10分钟后再次登录!"); } //update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户 //1. 校验用户是否有效 SysUser sysUser = sysUserService.getUserByName(username); result = sysUserService.checkUserIsEffective(sysUser); if(!result.isSuccess()) { return result; } //2. 校验用户名或密码是否正确 String userpassword = PasswordUtil.encrypt(username, password, sysUser.getSalt()); String syspassword = sysUser.getPassword(); if (!syspassword.equals(userpassword)) { //update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户 addLoginFailOvertimes(username); //update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户 result.error500("用户名或密码错误"); return result; } //3.设置登录部门 String orgCode = sysUser.getOrgCode(); if(oConvertUtils.isEmpty(orgCode)) { //如果当前用户无选择部门 查看部门关联信息 List departs = sysDepartService.queryUserDeparts(sysUser.getId()); //update-begin-author:taoyan date:20220117 for: JTC-1068【app】新建用户,没有设置部门及角色,点击登录提示暂未归属部,一直在登录页面 使用手机号登录 可正常 if (departs == null || departs.size() == 0) { /*result.error500("用户暂未归属部门,不可登录!"); return result;*/ }else{ orgCode = departs.get(0).getOrgCode(); sysUser.setOrgCode(orgCode); this.sysUserService.updateUserDepart(username, orgCode,null); } //update-end-author:taoyan date:20220117 for: JTC-1068【app】新建用户,没有设置部门及角色,点击登录提示暂未归属部,一直在登录页面 使用手机号登录 可正常 } //4. 设置登录租户 Result loginTenantError = sysUserService.setLoginTenant(sysUser, obj, username, result); if (loginTenantError != null) { return loginTenantError; } //5. 设置登录用户信息 obj.put("userInfo", sysUser); //6. 生成token String token = JwtUtil.sign(username, syspassword); // 设置超时时间 redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token); redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME*2 / 1000); //token 信息 obj.put("token", token); result.setResult(obj); result.setSuccess(true); result.setCode(200); baseCommonService.addLog("用户名: " + username + ",登录成功[移动端]!", CommonConstant.LOG_TYPE_1, null); return result; } /** * 图形验证码 * @param sysLoginModel * @return */ @RequestMapping(value = "/checkCaptcha", method = RequestMethod.POST) public Result checkCaptcha(@RequestBody SysLoginModel sysLoginModel){ String captcha = sysLoginModel.getCaptcha(); String checkKey = sysLoginModel.getCheckKey(); if(captcha==null){ return Result.error("验证码无效"); } String lowerCaseCaptcha = captcha.toLowerCase(); String realKey = Md5Util.md5Encode(lowerCaseCaptcha+checkKey, "utf-8"); Object checkCode = redisUtil.get(realKey); if(checkCode==null || !checkCode.equals(lowerCaseCaptcha)) { return Result.error("验证码错误"); } return Result.ok(); } /** * 登录二维码 */ @ApiOperation(value = "登录二维码", notes = "登录二维码") @GetMapping("/getLoginQrcode") public Result getLoginQrcode() { String qrcodeId = CommonConstant.LOGIN_QRCODE_PRE+IdWorker.getIdStr(); //定义二维码参数 Map params = new HashMap(5); params.put("qrcodeId", qrcodeId); //存放二维码唯一标识30秒有效 redisUtil.set(CommonConstant.LOGIN_QRCODE + qrcodeId, qrcodeId, 30); return Result.OK(params); } /** * 扫码二维码 */ @ApiOperation(value = "扫码登录二维码", notes = "扫码登录二维码") @PostMapping("/scanLoginQrcode") public Result scanLoginQrcode(@RequestParam String qrcodeId, @RequestParam String token) { Object check = redisUtil.get(CommonConstant.LOGIN_QRCODE + qrcodeId); if (oConvertUtils.isNotEmpty(check)) { //存放token给前台读取 redisUtil.set(CommonConstant.LOGIN_QRCODE_TOKEN+qrcodeId, token, 60); } else { return Result.error("二维码已过期,请刷新后重试"); } return Result.OK("扫码成功"); } /** * 获取用户扫码后保存的token */ @ApiOperation(value = "获取用户扫码后保存的token", notes = "获取用户扫码后保存的token") @GetMapping("/getQrcodeToken") public Result getQrcodeToken(@RequestParam String qrcodeId) { Object token = redisUtil.get(CommonConstant.LOGIN_QRCODE_TOKEN + qrcodeId); Map result = new HashMap(5); Object qrcodeIdExpire = redisUtil.get(CommonConstant.LOGIN_QRCODE + qrcodeId); if (oConvertUtils.isEmpty(qrcodeIdExpire)) { //二维码过期通知前台刷新 result.put("token", "-2"); return Result.OK(result); } if (oConvertUtils.isNotEmpty(token)) { result.put("success", true); result.put("token", token); } else { result.put("token", "-1"); } return Result.OK(result); } /** * 登录失败超出次数5 返回true * @param username * @return */ private boolean isLoginFailOvertimes(String username){ String key = CommonConstant.LOGIN_FAIL + username; Object failTime = redisUtil.get(key); if(failTime!=null){ Integer val = Integer.parseInt(failTime.toString()); if(val>5){ return true; } } return false; } /** * 记录登录失败次数 * @param username */ private void addLoginFailOvertimes(String username){ String key = CommonConstant.LOGIN_FAIL + username; Object failTime = redisUtil.get(key); Integer val = 0; if(failTime!=null){ val = Integer.parseInt(failTime.toString()); } // 1小时 redisUtil.set(key, ++val, 3600); } }