From b002592f4e0ef594dd1dc3cf46cb7503db4a3d21 Mon Sep 17 00:00:00 2001 From: thinkgem Date: Fri, 2 Aug 2024 20:02:09 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=86=E8=B4=A6=E5=8F=B7+=E6=89=8B=E6=9C=BA?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E7=A0=81=E7=99=BB=E5=BD=95=EF=BC=8C=E6=9B=BF?= =?UTF-8?q?=E6=8D=A2=E4=B8=BA=E6=89=8B=E6=9C=BA=E5=8F=B7+=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E7=A0=81=E7=99=BB=E5=BD=95=EF=BC=9B=E5=BD=93=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E6=89=8B=E6=9C=BA=E5=8F=B7=E7=BB=91=E5=AE=9A=E5=A4=9A?= =?UTF-8?q?=E4=B8=AA=E8=B4=A6=E5=8F=B7=E7=9A=84=E6=97=B6=E5=80=99=EF=BC=8C?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E8=AE=A9=E7=94=A8=E6=88=B7=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E7=9A=84=E8=B4=A6=E5=8F=B7=E8=BF=9B=E8=A1=8C?= =?UTF-8?q?=E7=99=BB=E5=BD=95=EF=BC=9B=E6=96=B0=E5=A2=9EuserService.findLi?= =?UTF-8?q?stByMobile=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/sys/web/AccountController.java | 126 ++++++++++++------ .../resources/views/modules/sys/sysLogin.html | 15 ++- .../resources/static/modules/sys/sysLogin.js | 16 ++- 3 files changed, 112 insertions(+), 45 deletions(-) diff --git a/modules/core/src/main/java/com/jeesite/modules/sys/web/AccountController.java b/modules/core/src/main/java/com/jeesite/modules/sys/web/AccountController.java index 9aed4fc4..e9dea7e6 100644 --- a/modules/core/src/main/java/com/jeesite/modules/sys/web/AccountController.java +++ b/modules/core/src/main/java/com/jeesite/modules/sys/web/AccountController.java @@ -5,6 +5,7 @@ package com.jeesite.modules.sys.web; import com.jeesite.common.codec.DesUtils; +import com.jeesite.common.collect.ListUtils; import com.jeesite.common.collect.MapUtils; import com.jeesite.common.config.Global; import com.jeesite.common.lang.StringUtils; @@ -37,7 +38,10 @@ import springfox.documentation.annotations.ApiIgnore; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Date; +import java.util.List; import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; /** * 账号自助服务Controller @@ -55,20 +59,19 @@ public class AccountController extends BaseController{ /** * 获取登录短信或邮件验证码 + * @param mobile 手机号码 * @param validCode 图片验证码,防止重复机器人。 - * @param validType 验证方式:mobile、email * @author ThinkGem */ @PostMapping(value = "getLoginValidCode") @ResponseBody @ApiOperation(value = "获取登录的短信或邮件验证码") @ApiImplicitParams({ - @ApiImplicitParam(name = "username", value = "登录账号", required = true, paramType="query", type="String"), + @ApiImplicitParam(name = "mobile", value = "登录手机号", required = true, paramType="query", type="String"), @ApiImplicitParam(name = "validCode", value = "图片验证码,防止重复机器人", required = true), - @ApiImplicitParam(name = "validType", value = "验证方式(mobile、email)", required = true), }) - public String getLoginValidCode(String username, String validCode, String validType, HttpServletRequest request) { - return getValidCode("login", username, validCode, validType, request, "登录验证码"); + public String getLoginValidCode(String mobile, String validCode, HttpServletRequest request) { + return getValidCode("login", mobile, validCode, "mobile", request, "登录验证码"); } /** @@ -80,19 +83,33 @@ public class AccountController extends BaseController{ @ApiOperation(value = "根据短信或邮件验证码登录系统") @ApiImplicitParams({ @ApiImplicitParam(name = "loginValidCode", value = "手机或邮箱接受的验证码", required = true), + @ApiImplicitParam(name = "selectLoginCode", value = "手机号绑定多个账号时的登录账号", required = true), }) - public String loginByValidCode(String loginValidCode, HttpServletRequest request, HttpServletResponse response) { + public String loginByValidCode(String selectLoginCode, String loginValidCode, HttpServletRequest request, HttpServletResponse response) { if (!Global.getConfigToBoolean("user.loginByValidCode", "true")) { return renderResult(Global.FALSE, "验证码登录未开启,请设置:user.loginByValidCode=true"); } - FormToken formToken = FormFilter.newToken(request, response); - String s = validValidCode("login", formToken.getUsername(), loginValidCode, request); + String type = "login"; + String userCode = UserUtils.getCache(type + "UserCode"); + String loginCode = UserUtils.getCache(type + "LoginCode"); + List userList = UserUtils.getCache(type + "UserList"); + String s = validValidCode(type, userCode, loginCode, loginValidCode, request); if (s != null) { return s; } // 登录系统 try { - formToken.setInnerLogin(true); // 因为手机验证码已验证,所以无需再进行验证密码 + if (StringUtils.isNotBlank(selectLoginCode) && ListUtils.isNotEmpty(userList)) { + Optional userOptional = userList.stream().filter(user -> selectLoginCode + .equals(user.getLoginCode())).findFirst(); + if (userOptional.isPresent()) { + User user = userOptional.get(); + loginCode = user.getLoginCode(); + } + } + FormToken formToken = FormFilter.newToken(request, response); + formToken.setUsername(loginCode); + formToken.setInnerLogin(true); UserUtils.getSubject().login(formToken); FormFilter.onLoginSuccess(request, response); } catch (AuthenticationException e) { @@ -138,23 +155,25 @@ public class AccountController extends BaseController{ @ApiImplicitParam(name = "fpValidCode", value = "手机或邮箱接受的验证码", required = true), @ApiImplicitParam(name = "password", value = "新密码", required = true, paramType="query", type="String"), }) - public String savePwdByValidCode(User user, String fpValidCode, HttpServletRequest request) { - String userCode = UserUtils.getCache("fp" + "UserCode"); - String s = validValidCode("fp", user.getLoginCode(), fpValidCode, request); + public String savePwdByValidCode(String password, String fpValidCode, HttpServletRequest request) { + String type = "fp"; + String userCode = UserUtils.getCache(type + "UserCode"); + String loginCode = UserUtils.getCache(type + "LoginCode"); + String s = validValidCode(type, userCode, loginCode, fpValidCode, request); if (s != null) { return s; } String secretKey = Global.getProperty("shiro.loginSubmit.secretKey"); if (StringUtils.isNotBlank(secretKey)){ - user.setPassword(DesUtils.decode(user.getPassword(), secretKey)); + password = DesUtils.decode(password, secretKey); } // 更新为新密码 try{ - userService.updatePassword(userCode, user.getPassword()); + userService.updatePassword(userCode, password); }catch(ServiceException se){ return renderResult(Global.FALSE, se.getMessage()); } - return renderResult(Global.TRUE, text("恭喜你,您的账号 {0} 密码找回成功!", user.getLoginCode())); + return renderResult(Global.TRUE, text("恭喜你,您的账号 {0} 密码找回成功!", loginCode)); } /** @@ -169,9 +188,34 @@ public class AccountController extends BaseController{ if (!"mobile".equals(validType) && !"email".equals(validType)){ return renderResult(Global.FALSE, text("非法操作。")); } - User u = UserUtils.getByLoginCode(loginCode); - if(u == null){ - return renderResult(Global.FALSE, text("登录账号不正确!")); + Map data = MapUtils.newHashMap(); + User u = null; + if ("login".equals(type)){ + User where = new User(); + where.setMobile(loginCode); + where.setStatus(User.STATUS_NORMAL); + List userList = userService.findListByMobile(where); + if (!userList.isEmpty()){ + u = userList.get(0); + if (userList.size() > 1) { + data.put("extMessage", text("该手机号绑定了多个账号,请选择一个账号登录")); + data.put("userList", userList.stream().map(user -> { + Map map = MapUtils.newHashMap(); + map.put("loginCode", user.getLoginCode()); + map.put("userName", user.getUserName()); + return map; + }).collect(Collectors.toList())); + } + UserUtils.putCache(type + "UserList", userList); + } + if(u == null){ + return renderResult(Global.FALSE, text("手机号不正确!")); + } + } else { + u = UserUtils.getByLoginCode(loginCode); + if(u == null){ + return renderResult(Global.FALSE, text("登录账号不正确!")); + } } if("mobile".equals(validType) && StringUtils.isBlank(u.getMobile())){ return renderResult(Global.FALSE, text("该账号未设置手机号码!")); @@ -179,7 +223,7 @@ public class AccountController extends BaseController{ return renderResult(Global.FALSE, text("该账号未设置邮件地址!")); } // 操作是否频繁验证, 如果离上次获取验证码小于20秒,则提示操作频繁。 - Date date = (Date)UserUtils.getCache(type + "LastDate"); + Date date = UserUtils.getCache(type + "LastDate"); if (date != null && (System.currentTimeMillis()-date.getTime())/(1000L) < 20L){ return renderResult(Global.FALSE, text("您当前操作太频繁,请稍等一会再操作!")); }else{ @@ -192,9 +236,9 @@ public class AccountController extends BaseController{ UserUtils.putCache(type + "ValidCode", loginValidCode); // 发送邮箱或短信验证码 if("mobile".equals(validType)){ - return sendSmsValidCode(u, loginValidCode, text(msgTitle)); + return sendSmsValidCode(u, loginValidCode, text(msgTitle), data); }else if("email".equals(validType)){ - return sendEmailValidCode(u, loginValidCode, text(msgTitle)); + return sendEmailValidCode(u, loginValidCode, text(msgTitle), data); } return null; } @@ -203,16 +247,15 @@ public class AccountController extends BaseController{ * 验证验证码 * @author ThinkGem */ - private String validValidCode(String type, String loginCode, String loginValidCode, HttpServletRequest request) { - String userCode = UserUtils.getCache(type + "UserCode"); - String loginCode2 = UserUtils.getCache(type + "LoginCode"); - String validCode = UserUtils.getCache(type + "ValidCode"); - Date date = (Date)UserUtils.getCache(type + "LastDate"); - - // 一同验证保存的用户名和验证码是否正确(如果只校验验证码,不验证用户名,则会有获取验证码后修改用户名的漏洞) - if (!(userCode != null && loginCode != null && loginCode.equals(loginCode2))){ + private String validValidCode(String type, String userCode, String loginCode, String loginValidCode, HttpServletRequest request) { + // 验证类型、用户名和登录账号,如果为空,则要求重新获取验证码 + if (StringUtils.isAnyBlank(type, userCode, loginCode)){ return renderResult(Global.FALSE, text("请重新获取验证码!")); } + + // 获取验证码和验证时间 + String validCode = UserUtils.getCache(type + "ValidCode"); + Date date = UserUtils.getCache(type + "LastDate"); // 验证码是否超时 boolean isTimeout = true; @@ -229,6 +272,7 @@ public class AccountController extends BaseController{ UserUtils.removeCache(type + "LoginCode"); UserUtils.removeCache(type + "ValidCode"); UserUtils.removeCache(type + "LastDate"); + UserUtils.removeCache(type + "UserList"); return null; } @@ -244,18 +288,18 @@ public class AccountController extends BaseController{ @ApiImplicitParam(name = "loginCode", value = "登录账号", required = true, paramType="query", type="String"), @ApiImplicitParam(name = "validCode", value = "图片验证码,防止重复机器人", required = true), }) - public String getPwdQuestion(User user, String validCode, HttpServletRequest request) { + public String getPwdQuestion(String loginCode, String validCode, HttpServletRequest request) { // 校验图片验证码,防止重复机器人。 if (!ValidCodeUtils.validate(request, validCode)){ return renderResult(Global.FALSE, text("图片验证码不正确或已失效,请点击图片刷新!")); } // 账号是否存在验证 - User u = UserUtils.getByLoginCode(user.getLoginCode()); + User u = UserUtils.getByLoginCode(loginCode); if (u == null){ return renderResult(Global.FALSE, text("登录账号不正确!")); } // 操作是否频繁验证, 如果离上次获取验证码小于20秒,则提示操作频繁。 - Date date = (Date)UserUtils.getCache("fpLastDate"); + Date date = UserUtils.getCache("fpLastDate"); if (date != null && (System.currentTimeMillis()-date.getTime())/(1000L) < 20L){ return renderResult(Global.FALSE, text("您当前操作太频繁,请稍等一会再操作!")); }else{ @@ -385,7 +429,7 @@ public class AccountController extends BaseController{ return renderResult(Global.FALSE, text("手机号码不能为空!")); } // 操作是否频繁验证,如果离上次获取验证码小于20秒,则提示操作频繁。 - Date date = (Date)UserUtils.getCache("regLastDate"); + Date date = UserUtils.getCache("regLastDate"); if (date != null && (System.currentTimeMillis()-date.getTime())/(1000L) < 20L){ return renderResult(Global.FALSE, text("您当前操作太频繁,请稍等一会再操作!")); }else{ @@ -413,9 +457,9 @@ public class AccountController extends BaseController{ UserUtils.putCache("regValidCode", regValidCode); // 发送邮箱或短信验证码 if("email".equals(validType)){ - return sendEmailValidCode(user, regValidCode, text("注册账号")); + return sendEmailValidCode(user, regValidCode, text("注册账号"), null); }else if("mobile".equals(validType)){ - return sendSmsValidCode(user, regValidCode, text("注册账号")); + return sendSmsValidCode(user, regValidCode, text("注册账号"), null); } return null; } @@ -423,7 +467,7 @@ public class AccountController extends BaseController{ /** * 根据短信或邮件验证码注册用户(通过邮箱、手机号) * @param user 用户信息参数 - * @param validType 验证方式:mobile、email + * @param regValidCode 注册验证码 */ @PostMapping(value = "saveRegByValidCode") @ResponseBody @@ -445,7 +489,7 @@ public class AccountController extends BaseController{ String email = UserUtils.getCache("regEmail"); String mobile = UserUtils.getCache("regMobile"); String validCode = UserUtils.getCache("regValidCode"); - Date date = (Date)UserUtils.getCache("regLastDate"); + Date date = UserUtils.getCache("regLastDate"); // 一同验证保存的用户名和验证码是否正确(如果只校验验证码,不验证用户名,则会有获取验证码后修改用户名的漏洞) if (!(loginCode != null && loginCode.equals(user.getLoginCode()))){ @@ -503,7 +547,7 @@ public class AccountController extends BaseController{ /** * 发送邮件验证码 */ - private String sendEmailValidCode(User user, String code, String title){ + private String sendEmailValidCode(User user, String code, String title, Map data){ String account = user.getEmail(); try { title = text("{0}({1}){2}验证码", user.getUserName(), user.getLoginCode(), title); @@ -517,13 +561,13 @@ public class AccountController extends BaseController{ return renderResult(Global.FALSE, text("系统出现了点问题,错误信息:{0}", e.getMessage())); } account = account.replaceAll("([\\w\\W]?)([\\w\\W]+)([\\w\\W])(@[\\w\\W]+)", "$1****$3$4"); - return renderResult(Global.TRUE, text("验证码已发送到“{0}”邮箱账号,请尽快查收!", account)); + return renderResult(Global.TRUE, text("验证码已发送到“{0}”邮箱账号,请尽快查收!", account), data); } /** * 发送短信验证码 */ - private String sendSmsValidCode(User user, String code, String title){ + private String sendSmsValidCode(User user, String code, String title, Map data){ String account = user.getMobile(); try { title = text("{0}({1}){2}验证码", user.getUserName(), user.getLoginCode(), title); @@ -536,7 +580,7 @@ public class AccountController extends BaseController{ return renderResult(Global.FALSE, text("系统出现了点问题,错误信息:{0}", e.getMessage())); } account = account.replaceAll("(\\d{3})(\\d+)(\\d{3})","$1****$3"); - return renderResult(Global.TRUE, text("验证码已发送到“{0}”的手机号码,请尽快查收!", account)); + return renderResult(Global.TRUE, text("验证码已发送到“{0}”的手机号码,请尽快查收!", account), data); } } diff --git a/modules/core/src/main/resources/views/modules/sys/sysLogin.html b/modules/core/src/main/resources/views/modules/sys/sysLogin.html index 0de2c2ac..80a36fb8 100644 --- a/modules/core/src/main/resources/views/modules/sys/sysLogin.html +++ b/modules/core/src/main/resources/views/modules/sys/sysLogin.html @@ -34,12 +34,17 @@ <% }else if(isNotBlank(message!)){ %> <% } %> -
+
<#form:input type="text" name="username" class="form-control required" data-msg-required="${text('请填写登录账号.')}" placeholder="${text('登录账号')}" value="${cookie('rememberUserCode')}"/>
+
+ + <#form:input type="text" name="mobile" class="form-control required" + data-msg-required="${text('请填写手机号码.')}" placeholder="${text('手机号码')}"/> +
+
+
+  ${text('选择账号')}: + +
+