新增手机号短信验证码登录 user.loginByValidCode=true;调整
sysLogin、sysIndex、menuTree、forgetPwd、registerUser 的目录,方便覆写和理解;增加 自定义主题视图 的 readme.txt 帮助文件。
This commit is contained in:
@@ -101,7 +101,7 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
|
||||
}
|
||||
// 登录用户名解密(解决登录用户名明文传输安全问题)
|
||||
String secretKey = Global.getProperty("shiro.loginSubmit.secretKey");
|
||||
if (StringUtils.isNotBlank(secretKey)){
|
||||
if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(secretKey)){
|
||||
username = DesUtils.decode(username, secretKey);
|
||||
if (StringUtils.isBlank(username)){
|
||||
logger.info("登录账号为空或解码错误.");
|
||||
@@ -128,7 +128,7 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
|
||||
}
|
||||
// 登录密码解密(解决登录密码明文传输安全问题)
|
||||
String secretKey = Global.getProperty("shiro.loginSubmit.secretKey");
|
||||
if (StringUtils.isNotBlank(secretKey)){
|
||||
if (StringUtils.isNotBlank(password) && StringUtils.isNotBlank(secretKey)){
|
||||
password = DesUtils.decode(password, secretKey);
|
||||
if (StringUtils.isBlank(password)){
|
||||
logger.info("登录密码为空或解码错误.");
|
||||
@@ -167,7 +167,7 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.
|
||||
}
|
||||
// 登录用户名解密(解决登录用户名明文传输安全问题)
|
||||
String secretKey = Global.getProperty("shiro.loginSubmit.secretKey");
|
||||
if (StringUtils.isNotBlank(secretKey)){
|
||||
if (StringUtils.isNotBlank(captcha) && StringUtils.isNotBlank(secretKey)){
|
||||
captcha = DesUtils.decode(captcha, secretKey);
|
||||
}
|
||||
return captcha;
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
*/
|
||||
package com.jeesite.modules.sys.web.user;
|
||||
package com.jeesite.modules.sys.web;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@@ -23,6 +25,8 @@ import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.common.msg.EmailUtils;
|
||||
import com.jeesite.common.msg.SmsUtils;
|
||||
import com.jeesite.common.service.ServiceException;
|
||||
import com.jeesite.common.shiro.authc.FormToken;
|
||||
import com.jeesite.common.shiro.filter.FormAuthenticationFilter;
|
||||
import com.jeesite.common.web.BaseController;
|
||||
import com.jeesite.modules.sys.entity.User;
|
||||
import com.jeesite.modules.sys.service.UserService;
|
||||
@@ -38,28 +42,77 @@ import io.swagger.annotations.ApiOperation;
|
||||
/**
|
||||
* 账号自助服务Controller
|
||||
* @author ThinkGem
|
||||
* @version 2017-12-7
|
||||
* @version 2020-9-20
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping(value = "/account")
|
||||
@ConditionalOnProperty(name="web.core.enabled", havingValue="true", matchIfMissing=true)
|
||||
@Api(tags = "Account / 账号自助服务、找回密码、账号注册")
|
||||
@Api(tags = "Account / 账号服务:验证码登录、找回密码、账号注册")
|
||||
public class AccountController extends BaseController{
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
/**
|
||||
* 获取登录短信或邮件验证码
|
||||
* @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 = "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, "登录验证码");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据短信或邮件验证码登录系统
|
||||
* @author ThinkGem
|
||||
*/
|
||||
@PostMapping(value = "loginByValidCode")
|
||||
@ResponseBody
|
||||
@ApiOperation(value = "根据短信或邮件验证码登录系统")
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "username", value = "登录账号", required = true, paramType="query", type="String"),
|
||||
@ApiImplicitParam(name = "loginValidCode", value = "手机或邮箱接受的验证码", required = true),
|
||||
})
|
||||
public String loginByValidCode(String username, String loginValidCode, HttpServletRequest request, HttpServletResponse response) {
|
||||
if (!Global.getConfigToBoolean("user.loginByValidCode", "true")) {
|
||||
return renderResult(Global.FALSE, "验证码登录未开启,请设置:user.loginByValidCode=true");
|
||||
}
|
||||
FormToken formToken = FormAuthenticationFilter.newToken(request, response);
|
||||
String s = validValidCode("login", formToken.getUsername(), loginValidCode, request);
|
||||
if (s != null) {
|
||||
return s;
|
||||
}
|
||||
// 登录系统
|
||||
try {
|
||||
formToken.setInnerLogin(true); // 因为手机验证码已验证,所以无需再进行验证密码
|
||||
UserUtils.getSubject().login(formToken);
|
||||
FormAuthenticationFilter.onLoginSuccess(request, response);
|
||||
} catch (AuthenticationException e) {
|
||||
FormAuthenticationFilter.onLoginFailure(e, request, response);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 忘记密码页面
|
||||
*/
|
||||
@GetMapping(value = "forgetPwd")
|
||||
@ApiOperation(value = "忘记密码页面")
|
||||
public String forgetPwd(Model model) {
|
||||
return "modules/sys/account/forgetPwd";
|
||||
return "modules/sys/forgetPwd";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取找回密码短信、邮件验证码
|
||||
* 获取找回密码短信或邮件验证码
|
||||
* @param validCode 图片验证码,防止重复机器人。
|
||||
* @param validType 验证方式:mobile、email
|
||||
*/
|
||||
@@ -72,41 +125,7 @@ public class AccountController extends BaseController{
|
||||
@ApiImplicitParam(name = "validType", value = "验证方式(mobile、email)", required = true),
|
||||
})
|
||||
public String getFpValidCode(User user, String validCode, String validType, HttpServletRequest request) {
|
||||
// 校验图片验证码,防止重复机器人。
|
||||
if (!ValidCodeUtils.validate(request, validCode)){
|
||||
return renderResult(Global.FALSE, text("图片验证码不正确或已失效,请点击图片刷新!"));
|
||||
}
|
||||
if (!"mobile".equals(validType) && !"email".equals(validType)){
|
||||
return renderResult(Global.FALSE, text("非法操作。"));
|
||||
}
|
||||
User u = UserUtils.getByLoginCode(user.getLoginCode());
|
||||
if(u == null){
|
||||
return renderResult(Global.FALSE, text("登录账号不正确!"));
|
||||
}
|
||||
if("mobile".equals(validType) && StringUtils.isBlank(u.getMobile())){
|
||||
return renderResult(Global.FALSE, text("该账号未设置手机号码!"));
|
||||
}else if("email".equals(validType) && StringUtils.isBlank(u.getEmail())){
|
||||
return renderResult(Global.FALSE, text("该账号未设置邮件地址!"));
|
||||
}
|
||||
// 操作是否频繁验证, 如果离上次获取验证码小于20秒,则提示操作频繁。
|
||||
Date date = (Date)UserUtils.getCache("fpLastDate");
|
||||
if (date != null && (System.currentTimeMillis()-date.getTime())/(1000L) < 20L){
|
||||
return renderResult(Global.FALSE, text("您当前操作太频繁,请稍等一会再操作!"));
|
||||
}else{
|
||||
UserUtils.putCache("fpLastDate", new Date());
|
||||
}
|
||||
// 生成验证码,并缓存。
|
||||
String fpValidCode = StringUtils.getRandomNum(6);
|
||||
UserUtils.putCache("fpUserCode", u.getUserCode());
|
||||
UserUtils.putCache("fpLoginCode", u.getLoginCode());
|
||||
UserUtils.putCache("fpValidCode", fpValidCode);
|
||||
// 发送邮箱或短信验证码
|
||||
if("mobile".equals(validType)){
|
||||
return sendSmsValidCode(u, fpValidCode, text("找回密码"));
|
||||
}else if("email".equals(validType)){
|
||||
return sendEmailValidCode(u, fpValidCode, text("找回密码"));
|
||||
}
|
||||
return null;
|
||||
return getValidCode("fp", user.getLoginCode(), validCode, validType, request, "找回密码");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,39 +140,93 @@ public class AccountController extends BaseController{
|
||||
@ApiImplicitParam(name = "password", value = "新密码", required = true, paramType="query", type="String"),
|
||||
})
|
||||
public String savePwdByValidCode(User user, String fpValidCode, HttpServletRequest request) {
|
||||
String userCode = (String)UserUtils.getCache("fpUserCode");
|
||||
String loginCode = (String)UserUtils.getCache("fpLoginCode");
|
||||
String validCode = (String)UserUtils.getCache("fpValidCode");
|
||||
Date date = (Date)UserUtils.getCache("fpLastDate");
|
||||
String s = validValidCode("fp", user.getLoginCode(), fpValidCode, request);
|
||||
if (s != null) {
|
||||
return s;
|
||||
}
|
||||
// 更新为新密码
|
||||
try{
|
||||
userService.updatePassword(user.getUserCode(), user.getPassword());
|
||||
}catch(ServiceException se){
|
||||
return renderResult(Global.FALSE, se.getMessage());
|
||||
}
|
||||
return renderResult(Global.TRUE, text("恭喜你,您的账号 {0} 密码修改成功!", user.getUserCode()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取验证码
|
||||
* @author ThinkGem
|
||||
*/
|
||||
private String getValidCode(String type, String loginCode, String validCode, String validType, HttpServletRequest request, String msgTitle) {
|
||||
// 校验图片验证码,防止重复机器人。
|
||||
if (!ValidCodeUtils.validate(request, validCode)){
|
||||
return renderResult(Global.FALSE, text("图片验证码不正确或已失效,请点击图片刷新!"));
|
||||
}
|
||||
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("登录账号不正确!"));
|
||||
}
|
||||
if("mobile".equals(validType) && StringUtils.isBlank(u.getMobile())){
|
||||
return renderResult(Global.FALSE, text("该账号未设置手机号码!"));
|
||||
}else if("email".equals(validType) && StringUtils.isBlank(u.getEmail())){
|
||||
return renderResult(Global.FALSE, text("该账号未设置邮件地址!"));
|
||||
}
|
||||
// 操作是否频繁验证, 如果离上次获取验证码小于20秒,则提示操作频繁。
|
||||
Date date = (Date)UserUtils.getCache(type + "LastDate");
|
||||
if (date != null && (System.currentTimeMillis()-date.getTime())/(1000L) < 20L){
|
||||
return renderResult(Global.FALSE, text("您当前操作太频繁,请稍等一会再操作!"));
|
||||
}else{
|
||||
UserUtils.putCache(type + "LastDate", new Date());
|
||||
}
|
||||
// 生成验证码,并缓存。
|
||||
String loginValidCode = StringUtils.getRandomNum(6);
|
||||
UserUtils.putCache(type + "UserCode", u.getUserCode());
|
||||
UserUtils.putCache(type + "LoginCode", u.getLoginCode());
|
||||
UserUtils.putCache(type + "ValidCode", loginValidCode);
|
||||
// 发送邮箱或短信验证码
|
||||
if("mobile".equals(validType)){
|
||||
return sendSmsValidCode(u, loginValidCode, text(msgTitle));
|
||||
}else if("email".equals(validType)){
|
||||
return sendEmailValidCode(u, loginValidCode, text(msgTitle));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证验证码
|
||||
* @author ThinkGem
|
||||
*/
|
||||
private String validValidCode(String type, String loginCode, String loginValidCode, HttpServletRequest request) {
|
||||
String userCode = (String)UserUtils.getCache(type + "UserCode");
|
||||
String loginCode2 = (String)UserUtils.getCache(type + "LoginCode");
|
||||
String validCode = (String)UserUtils.getCache(type + "ValidCode");
|
||||
Date date = (Date)UserUtils.getCache(type + "LastDate");
|
||||
|
||||
// 一同验证保存的用户名和验证码是否正确(如果只校验验证码,不验证用户名,则会有获取验证码后修改用户名的漏洞)
|
||||
if (!(userCode != null && loginCode != null && loginCode.equals(user.getLoginCode()))){
|
||||
if (!(userCode != null && loginCode != null && loginCode.equals(loginCode2))){
|
||||
return renderResult(Global.FALSE, text("请重新获取验证码!"));
|
||||
}
|
||||
|
||||
// 清理验证码,验证码只允许使用一次。
|
||||
UserUtils.removeCache("fpUserCode");
|
||||
UserUtils.removeCache("fpLoginCode");
|
||||
UserUtils.removeCache("fpValidCode");
|
||||
UserUtils.removeCache("fpLastDate");
|
||||
|
||||
// 验证码是否超时
|
||||
boolean isTimeout = true;
|
||||
String validTime = Global.getConfig("sys.account.validCodeTimeout", "10"); //验证码有效时间(单位分钟,0表示不限制,默认值10)
|
||||
if("0".equals(validTime) || (date != null && (System.currentTimeMillis()-date.getTime())/(1000L) < 60*Long.parseLong(validTime))){
|
||||
isTimeout = false;
|
||||
}
|
||||
if (!(validCode != null && validCode.equals(fpValidCode) && !isTimeout)){
|
||||
if (!(validCode != null && validCode.equals(loginValidCode) && !isTimeout)){
|
||||
return renderResult(Global.FALSE, text("验证码不正确或已失效,请重新获取验证码!"));
|
||||
}
|
||||
|
||||
// 更新为新密码。
|
||||
try{
|
||||
userService.updatePassword(userCode, user.getPassword());
|
||||
}catch(ServiceException se){
|
||||
return renderResult(Global.FALSE, se.getMessage());
|
||||
}
|
||||
return renderResult(Global.TRUE, text("恭喜你,您的账号 {0} 密码修改成功!", loginCode));
|
||||
// 验证成功后,清理缓存
|
||||
UserUtils.removeCache(type + "UserCode");
|
||||
UserUtils.removeCache(type + "LoginCode");
|
||||
UserUtils.removeCache(type + "ValidCode");
|
||||
UserUtils.removeCache(type + "LastDate");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -225,10 +298,6 @@ public class AccountController extends BaseController{
|
||||
return renderResult(Global.FALSE, text("请重新获取保密问题!"));
|
||||
}
|
||||
|
||||
// 清理保密问题,每次获取只允许使用一次。
|
||||
UserUtils.removeCache("fpUserCode");
|
||||
UserUtils.removeCache("fpLoginCode");
|
||||
|
||||
// 验证三个密保问题是否正确。
|
||||
User u = UserUtils.getByLoginCode(user.getLoginCode());
|
||||
if (!(u != null && loginCode.equals(user.getLoginCode())
|
||||
@@ -244,6 +313,11 @@ public class AccountController extends BaseController{
|
||||
}catch(ServiceException se){
|
||||
return renderResult(Global.FALSE, se.getMessage());
|
||||
}
|
||||
|
||||
// 更新密码后,清理缓存
|
||||
UserUtils.removeCache("fpUserCode");
|
||||
UserUtils.removeCache("fpLoginCode");
|
||||
|
||||
return renderResult(Global.TRUE, text("验证通过"));
|
||||
}
|
||||
|
||||
@@ -254,7 +328,7 @@ public class AccountController extends BaseController{
|
||||
@GetMapping(value = "registerUser")
|
||||
@ApiOperation(value = "用户注册页面")
|
||||
public String registerUser(User user, HttpServletRequest request) {
|
||||
return "modules/sys/account/registerUser";
|
||||
return "modules/sys/registerUser";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -399,7 +473,7 @@ public class AccountController extends BaseController{
|
||||
u.setStatus(User.STATUS_AUDIT); // 待审核状态
|
||||
userService.save(u);
|
||||
|
||||
// 验证成功后清理验证码,验证码只允许使用一次。
|
||||
// 注册用户后,清理缓存
|
||||
UserUtils.removeCache("regCorpCode");
|
||||
UserUtils.removeCache("regCorpName");
|
||||
UserUtils.removeCache("regUserType");
|
||||
@@ -131,6 +131,9 @@ user:
|
||||
|
||||
# 登录账号是否租户内唯一,否则全局唯一
|
||||
loginCodeCorpUnique: false
|
||||
|
||||
# 是否启用验证码登录(手机、邮箱)
|
||||
loginByValidCode: true
|
||||
|
||||
# 用户类型配置信息(employee员工,member会员,btype往来单位,persion个人,expert专家,...),JSON 格式说明如下:
|
||||
# {"用户类型":{"beanName":"Service或Dao的Bean名称","loginView":"登录页面视图","indexView":"主框架页面视图,支持 redirect: 前缀"}}
|
||||
|
||||
@@ -69,6 +69,10 @@
|
||||
|
||||
登录=Login
|
||||
欢迎回来=Welcome
|
||||
账号登录=Login
|
||||
手机登录=Mobile
|
||||
没有账号=No account
|
||||
点击注册=Register
|
||||
|
||||
请填写登录账号.=Please enter login account.
|
||||
登录账号=Login account
|
||||
@@ -77,6 +81,11 @@
|
||||
请填写登录密码.=Please enter login password.
|
||||
登录密码=Login password
|
||||
|
||||
登录租户=Login tenant
|
||||
请填写手机验证码.=Please enter mobile valid code
|
||||
手机验证码=Mobile valid code
|
||||
获取手机验证码=Get valid code
|
||||
|
||||
公共场所慎用,下次不需要再填写帐号=Use caution in public places.
|
||||
记住账号=Remember account
|
||||
公共场所慎用,下次不需要再填写帐号和密码=Use caution in public places.
|
||||
|
||||
@@ -70,6 +70,10 @@
|
||||
|
||||
登录=ログイン
|
||||
欢迎回来=おかえり
|
||||
账号登录=ログイン
|
||||
手机登录=電話登録
|
||||
没有账号=アカウントなし
|
||||
点击注册=きにゅう
|
||||
|
||||
请填写登录账号.=ログインIDを入力してください.
|
||||
登录账号=ログインアカウント
|
||||
@@ -78,6 +82,11 @@
|
||||
请填写登录密码.=パスワードを入力してください.
|
||||
登录密码=パスワード
|
||||
|
||||
登录租户=テナント登録
|
||||
请填写手机验证码.=携帯電話の検証コード
|
||||
手机验证码=電話の検証コード
|
||||
获取手机验证码=コードを取得
|
||||
|
||||
公共场所慎用,下次不需要再填写帐号=次回からログインIDの入力が不要にします.
|
||||
记住账号=ログインID記憶
|
||||
公共场所慎用,下次不需要再填写帐号和密码=次回からパスワードの入力が不要にします.
|
||||
@@ -90,6 +99,9 @@
|
||||
注册账号=アカウント作成
|
||||
忘记密码=パスワードを忘れた
|
||||
|
||||
注册账号=アカウントを登録する
|
||||
忘记密码=パスワードを忘れる
|
||||
|
||||
# =========== 主框架页 ===========
|
||||
|
||||
仪表盘=計器盤
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/*!
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
*
|
||||
* @author ThinkGem
|
||||
* @version 2019-1-6
|
||||
*/
|
||||
$(function(){
|
||||
|
||||
$('#fp_validType').change(function(){
|
||||
var val = $(this).val(), action = '';
|
||||
$('.fp-element').addClass('hide').removeClass('block');
|
||||
$('.fp-'+val).addClass('block').removeClass('hide');
|
||||
setTimeout(function(){
|
||||
$('#fp_loginCode').focus();
|
||||
}, 100);
|
||||
if (val == 'mobile' || val == 'email'){
|
||||
var txt = (val == 'mobile' ? '手机' : '邮箱')
|
||||
$('#fpValidCode').attr('placeholder', txt+'验证码')
|
||||
.attr('data-msg-required', '请填写'+txt+'验证码.');
|
||||
$('#sendFpValidCode').val('获取'+txt+'验证码');
|
||||
action = ctxPath + '/account/savePwdByValidCode';
|
||||
}else if(val == 'question'){
|
||||
action = ctxPath + '/account/savePwdByPwdQuestion';
|
||||
}
|
||||
$('#forgetForm').attr('action', action);
|
||||
}).change();
|
||||
|
||||
var waitTime = 60;
|
||||
function sendTime(o) {
|
||||
if (waitTime == 0) {
|
||||
o.removeAttribute("disabled");
|
||||
o.value = "获取验证码";
|
||||
waitTime = 60;
|
||||
} else {
|
||||
o.setAttribute("disabled", true);
|
||||
o.value = "重新发送(" + waitTime + ")";
|
||||
waitTime--;
|
||||
setTimeout(function() {
|
||||
sendTime(o)
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
$('#sendFpValidCode').click(function() {
|
||||
var $this = this;
|
||||
js.ajaxSubmit(ctxPath + '/account/getFpValidCode', {
|
||||
validType: $('#fp_validType').val(),
|
||||
loginCode : $('#fp_loginCode').val(),
|
||||
validCode : $('#fp_validCode').val()
|
||||
}, function(data){
|
||||
js.showMessage(data.message);
|
||||
if (data.result == 'true'){
|
||||
sendTime($this);
|
||||
$('#fpValidCode').focus();
|
||||
}else{
|
||||
$('#fp_validCodeImg').click();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#fp_getQuestion').click(function() {
|
||||
js.ajaxSubmit(ctxPath + '/account/getPwdQuestion', {
|
||||
loginCode : $('#fp_loginCode').val(),
|
||||
validCode : $('#fp_validCode').val()
|
||||
}, function(data){
|
||||
js.showMessage(data.message);
|
||||
if (data.result == 'true'){
|
||||
$('#fp_q1').text(data.pwdQuestion);
|
||||
$('#fp_q2').text(data.pwdQuestion2);
|
||||
$('#fp_q3').text(data.pwdQuestion3);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#forgetForm').validate({
|
||||
ignore: ":hidden",
|
||||
submitHandler: function(form) {
|
||||
js.ajaxSubmitForm($(form), function(data){
|
||||
if (data.result == "true"){
|
||||
alert(data.message);
|
||||
location = ctx + '/login';
|
||||
}else{
|
||||
js.showMessage(data.message);
|
||||
$('#forgetForm').reset();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('#btnReset').click(function(){
|
||||
location = ctx + '/login';
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*!
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
*
|
||||
* @author ThinkGem
|
||||
* @version 2019-1-6
|
||||
*/
|
||||
$(function(){
|
||||
|
||||
$('#reg_validType').change(function(){
|
||||
var val = $(this).val(), action = '';
|
||||
$('.reg-element').addClass('hide').removeClass('block');
|
||||
$('.reg-'+val).addClass('block').removeClass('hide');
|
||||
setTimeout(function(){
|
||||
$('#reg_loginCode').focus();
|
||||
}, 100);
|
||||
if (val == 'mobile' || val == 'email'){
|
||||
var txt = (val == 'mobile' ? '手机' : '邮箱')
|
||||
$('#regValidCode').attr('placeholder', txt+'验证码')
|
||||
.attr('data-msg-required', '请填写'+txt+'验证码.');
|
||||
$('#sendRegValidCode').val('获取'+txt+'验证码');
|
||||
action = ctxPath + '/account/saveRegByValidCode';
|
||||
}else if(val == 'question'){
|
||||
action = ctxPath + '/account/savePwdByPwdQuestion';
|
||||
}
|
||||
$('#registerForm').attr('action', action);
|
||||
}).change();
|
||||
|
||||
var waitTime = 60;
|
||||
function sendTime(o) {
|
||||
if (waitTime == 0) {
|
||||
o.removeAttribute("disabled");
|
||||
o.value = "获取验证码";
|
||||
waitTime = 60;
|
||||
} else {
|
||||
o.setAttribute("disabled", true);
|
||||
o.value = "重新发送(" + waitTime + ")";
|
||||
waitTime--;
|
||||
setTimeout(function() {
|
||||
sendTime(o)
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
$('#sendRegValidCode').click(function() {
|
||||
var $this = this;
|
||||
js.ajaxSubmit(ctxPath + '/account/getRegValidCode', {
|
||||
validType: $('#reg_validType').val(),
|
||||
corpCode_ : $('#reg_corpCode').val(),
|
||||
corpName_ : $('#reg_corpName').val(),
|
||||
loginCode : $('#reg_loginCode').val(),
|
||||
userName : $('#reg_userName').val(),
|
||||
email : $('#reg_email').val(),
|
||||
mobile : $('#reg_mobile').val(),
|
||||
userType: $('#reg_userType').val(),
|
||||
validCode : $('#reg_validCode').val()
|
||||
}, function(data){
|
||||
js.showMessage(data.message);
|
||||
if (data.result == 'true'){
|
||||
sendTime($this);
|
||||
$('#regValidCode').focus();
|
||||
}else{
|
||||
$('#reg_validCodeImg').click();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#registerForm').validate({
|
||||
ignore: ":hidden",
|
||||
submitHandler: function(form) {
|
||||
js.ajaxSubmitForm($(form), function(data){
|
||||
if (data.result == "true"){
|
||||
alert(data.message);
|
||||
location = ctx + '/login';
|
||||
}else{
|
||||
js.showMessage(data.message);
|
||||
$('#registerForm').reset();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('#btnReset').click(function(){
|
||||
location = ctx + '/login';
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -16,28 +16,6 @@
|
||||
<option value="email">使用电子邮箱找回您的密码</option>
|
||||
<option value="question">使用保密问题找回您的密码</option>
|
||||
</select>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
$('#fp_validType').change(function(){
|
||||
var val = $(this).val(), action = '';
|
||||
$('.fp-element').addClass('hide').removeClass('block');
|
||||
$('.fp-'+val).addClass('block').removeClass('hide');
|
||||
setTimeout(function(){
|
||||
$('#fp_loginCode').focus();
|
||||
}, 100);
|
||||
if (val == 'mobile' || val == 'email'){
|
||||
var txt = (val == 'mobile' ? '手机' : '邮箱')
|
||||
$('#fpValidCode').attr('placeholder', txt+'验证码')
|
||||
.attr('data-msg-required', '请填写'+txt+'验证码.');
|
||||
$('#sendFpValidCode').val('获取'+txt+'验证码');
|
||||
action = '${ctxPath}/account/savePwdByValidCode';
|
||||
}else if(val == 'question'){
|
||||
action = '${ctxPath}/account/savePwdByPwdQuestion';
|
||||
}
|
||||
$('#forgetForm').attr('action', action);
|
||||
}).change();
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
<div class="form-group has-feedback">
|
||||
<span class="fa fa-user form-control-feedback"></span>
|
||||
@@ -54,54 +32,9 @@
|
||||
<input type="button" id="sendFpValidCode" value="获取手机验证码" class="btn btn-flat"/>
|
||||
</span>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
var waitTime = 60;
|
||||
function sendTime(o) {
|
||||
if (waitTime == 0) {
|
||||
o.removeAttribute("disabled");
|
||||
o.value = "获取验证码";
|
||||
waitTime = 60;
|
||||
} else {
|
||||
o.setAttribute("disabled", true);
|
||||
o.value = "重新发送(" + waitTime + ")";
|
||||
waitTime--;
|
||||
setTimeout(function() {
|
||||
sendTime(o)
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
$('#sendFpValidCode').click(function() {
|
||||
var $this = this;
|
||||
js.ajaxSubmit('${ctxPath}/account/getFpValidCode', {
|
||||
validType: $('#fp_validType').val(),
|
||||
loginCode : $('#fp_loginCode').val(),
|
||||
validCode : $('#fp_validCode').val()
|
||||
}, function(data){
|
||||
js.showMessage(data.message);
|
||||
if (data.result == 'true'){
|
||||
sendTime($this);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
<div class="form-group has-feedback fp-element fp-question clearfix">
|
||||
<input type="button" id="fp_getQuestion" value="获取保密问题" class="btn btn-default btn-block btn-flat"/>
|
||||
<script type="text/javascript">
|
||||
$('#fp_getQuestion').click(function() {
|
||||
js.ajaxSubmit('${ctxPath}/account/getPwdQuestion', {
|
||||
loginCode : $('#fp_loginCode').val(),
|
||||
validCode : $('#fp_validCode').val()
|
||||
}, function(data){
|
||||
js.showMessage(data.message);
|
||||
if (data.result == 'true'){
|
||||
$('#fp_q1').text(data.pwdQuestion);
|
||||
$('#fp_q2').text(data.pwdQuestion2);
|
||||
$('#fp_q3').text(data.pwdQuestion3);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
<div class="form-group has-feedback fp-element fp-question">
|
||||
问题1:<span id="fp_q1"></span>
|
||||
@@ -167,22 +100,4 @@
|
||||
<script>var secretKey = '${@Global.getConfig("shiro.loginSubmit.secretKey")}';</script>
|
||||
<script src="${ctxStatic}/jquery-toastr/2.1/toastr.min.js?${_version}"></script>
|
||||
<script src="${ctxStatic}/common/des.js?${_version}"></script>
|
||||
<script>
|
||||
$('#forgetForm').validate({
|
||||
ignore: ":hidden",
|
||||
submitHandler: function(form) {
|
||||
js.ajaxSubmitForm($(form), function(data){
|
||||
if (data.result == "true"){
|
||||
alert(data.message);
|
||||
location = "${ctx}/login";
|
||||
}else{
|
||||
js.showMessage(data.message);
|
||||
$('#forgetForm').reset();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
$('#btnReset').click(function(){
|
||||
location = '${ctx}/login';
|
||||
});
|
||||
</script>
|
||||
<script src="${ctxStatic}/modules/sys/forgetPwd.js?${_version}"></script>
|
||||
@@ -15,28 +15,6 @@
|
||||
<option value="email">使用电子邮箱注册账号</option>
|
||||
<option value="mobile">使用手机号码注册账号</option>
|
||||
</select>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
$('#reg_validType').change(function(){
|
||||
var val = $(this).val(), action = '';
|
||||
$('.reg-element').addClass('hide').removeClass('block');
|
||||
$('.reg-'+val).addClass('block').removeClass('hide');
|
||||
setTimeout(function(){
|
||||
$('#reg_loginCode').focus();
|
||||
}, 100);
|
||||
if (val == 'mobile' || val == 'email'){
|
||||
var txt = (val == 'mobile' ? '手机' : '邮箱')
|
||||
$('#regValidCode').attr('placeholder', txt+'验证码')
|
||||
.attr('data-msg-required', '请填写'+txt+'验证码.');
|
||||
$('#sendRegValidCode').val('获取'+txt+'验证码');
|
||||
action = '${ctxPath}/account/saveRegByValidCode';
|
||||
}else if(val == 'question'){
|
||||
action = '${ctxPath}/account/savePwdByPwdQuestion';
|
||||
}
|
||||
$('#registerForm').attr('action', action);
|
||||
}).change();
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
<% if(@Global.isUseCorpModel()){ %>
|
||||
<div class="form-group has-feedback">
|
||||
@@ -75,42 +53,6 @@
|
||||
<input type="button" id="sendRegValidCode" value="获取手机验证码" class="btn btn-flat"/>
|
||||
</span>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
var waitTime = 60;
|
||||
function sendTime(o) {
|
||||
if (waitTime == 0) {
|
||||
o.removeAttribute("disabled");
|
||||
o.value = "获取验证码";
|
||||
waitTime = 60;
|
||||
} else {
|
||||
o.setAttribute("disabled", true);
|
||||
o.value = "重新发送(" + waitTime + ")";
|
||||
waitTime--;
|
||||
setTimeout(function() {
|
||||
sendTime(o)
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
$('#sendRegValidCode').click(function() {
|
||||
var $this = this;
|
||||
js.ajaxSubmit('${ctxPath}/account/getRegValidCode', {
|
||||
validType: $('#reg_validType').val(),
|
||||
corpCode_ : $('#reg_corpCode').val(),
|
||||
corpName_ : $('#reg_corpName').val(),
|
||||
loginCode : $('#reg_loginCode').val(),
|
||||
userName : $('#reg_userName').val(),
|
||||
email : $('#reg_email').val(),
|
||||
mobile : $('#reg_mobile').val(),
|
||||
userType: $('#reg_userType').val(),
|
||||
validCode : $('#reg_validCode').val()
|
||||
}, function(data){
|
||||
js.showMessage(data.message);
|
||||
if (data.result == 'true'){
|
||||
sendTime($this);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
<div class="form-group has-feedback">
|
||||
<span class="fa fa-lock form-control-feedback"></span>
|
||||
@@ -152,22 +94,4 @@
|
||||
</div>
|
||||
<% } %>
|
||||
<script src="${ctxStatic}/jquery-toastr/2.1/toastr.min.js?${_version}"></script>
|
||||
<script>
|
||||
$('#registerForm').validate({
|
||||
ignore: ":hidden",
|
||||
submitHandler: function(form) {
|
||||
js.ajaxSubmitForm($(form), function(data){
|
||||
if (data.result == "true"){
|
||||
alert(data.message);
|
||||
location = "${ctx}/login";
|
||||
}else{
|
||||
js.showMessage(data.message);
|
||||
$('#registerForm').reset();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
$('#btnReset').click(function(){
|
||||
location = '${ctx}/login';
|
||||
});
|
||||
</script>
|
||||
<script src="${ctxStatic}/modules/sys/registerUser.js?${_version}"></script>
|
||||
@@ -9,10 +9,10 @@ var bodyClass = 'fixed noscroll2 sidebar-mini ' + sidebarCollapse;
|
||||
<link rel="stylesheet" href="${ctxStatic}/jquery-toastr/2.1/toastr.min.css?${_version}">
|
||||
<link rel="stylesheet" href="${ctxStatic}/modules/sys/sysIndex.css?${_version}">
|
||||
<header class="main-header">
|
||||
<% include('sysIndex/topMenu.html'){} %>
|
||||
<% include('/include/sysIndex/topMenu.html'){} %>
|
||||
</header>
|
||||
<aside class="main-sidebar">
|
||||
<% include('sysIndex/leftMenu.html'){} %>
|
||||
<% include('/include/sysIndex/leftMenu.html'){} %>
|
||||
</aside>
|
||||
<div class="content-wrapper">
|
||||
<div id="tabpanel"></div>
|
||||
@@ -9,27 +9,23 @@
|
||||
<small>${@Global.getConfig('productVersion')}</small></a>
|
||||
</div>
|
||||
<div class="login-box-body">
|
||||
<#form:form id="loginForm" model="${user!}" action="${ctx}/login" method="post">
|
||||
<h4 class="login-box-msg">${isNotBlank(message!)?message:text('欢迎回来')+'!'}</h4>
|
||||
<!-- <ul class="nav nav-tabs mb20">
|
||||
<li class="active"><a href="#tab-1" data-toggle="tab">账号登录</a></li>
|
||||
<li><a href="#tab-2" data-toggle="tab">邮箱登录</a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane active" id="tab-1"></div>
|
||||
<div class="tab-pane" id="tab-2"></div>
|
||||
</div> -->
|
||||
<ul id="loginTab" class="nav nav-tabs ${@Global.getConfigToBoolean('user.loginByValidCode','true')?'':'hide'}">
|
||||
<li class="active"><a href="#tab-1" data-toggle="tab" action="${ctx}/login">${text('账号登录')}</a></li>
|
||||
<li><a href="#tab-2" data-toggle="tab" action="${ctxPath}/account/loginByValidCode">${text('手机登录')}</a></li>
|
||||
</ul>
|
||||
<#form:form id="loginForm" model="${user!}" action="${ctx}/login" method="post" class="tab-content">
|
||||
<% if(isNotBlank(message!)){ %>
|
||||
<h5 class="login-box-msg text-red">${message}</h5>
|
||||
<% } %>
|
||||
<div class="form-group has-feedback">
|
||||
<span class="icon-user form-control-feedback" title="${text('登录账号')}"></span>
|
||||
<#form:input type="text" name="username" class="form-control required"
|
||||
data-msg-required="${text('请填写登录账号.')}" placeholder="${text('登录账号')}"
|
||||
value="${cookie('rememberUserCode')}"/>
|
||||
</div>
|
||||
<div class="form-group has-feedback">
|
||||
<span class="icon-lock form-control-feedback"
|
||||
title="${text('登录密码,鼠标按下显示密码')}"
|
||||
onmousedown="$('#password').attr('type','text')"
|
||||
onmouseup="$('#password').attr('type','password')"
|
||||
<div class="form-group has-feedback tab-pane tab-1 active">
|
||||
<span class="icon-lock form-control-feedback" title="${text('登录密码,鼠标按下显示密码')}"
|
||||
onmousedown="$('#password').attr('type','text')" onmouseup="$('#password').attr('type','password')"
|
||||
onmouseenter="$(this).removeClass('icon-lock').addClass('icon-eye')"
|
||||
onmouseout="$(this).removeClass('icon-eye').addClass('icon-lock')"></span>
|
||||
<#form:input type="password" name="password" class="form-control required"
|
||||
@@ -44,6 +40,15 @@
|
||||
<div class="form-group has-feedback" id="isValidCodeLogin" style="display:${isValidCodeLogin?'blank':'none'}">
|
||||
<#form:validcode name="validCode" isRequired="true" isRemote="true" isLazy="${!isValidCodeLogin}"/>
|
||||
</div>
|
||||
<div class="form-group has-feedback tab-pane tab-2">
|
||||
<div class="input-group">
|
||||
<input type="text" id="loginValidCode" name="loginValidCode" class="form-control required"
|
||||
data-msg-required="${text('请填写手机验证码.')}" placeholder="${text('手机验证码')}" />
|
||||
<span class="input-group-btn">
|
||||
<input type="button" id="sendLoginValidCode" value="${text('获取手机验证码')}" class="btn btn-flat"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mt5 icheck">
|
||||
<label title="${text('公共场所慎用,下次不需要再填写帐号')}"><input type="checkbox"
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
======= 说明:
|
||||
|
||||
当前目录:/src/main/resources/views/themes/default/modules/
|
||||
|
||||
是【default】主题的模块视图目录,该目录下的文件,会自动覆盖:
|
||||
|
||||
/src/main/resources/views/modules/ 下的默认视图文件。
|
||||
|
||||
======= 举例:
|
||||
|
||||
拷贝文件:/src/main/resources/views/modules/sys/sysLogin.html
|
||||
|
||||
复制到:/src/main/resources/views/themes/default/modules/sys/sysLogin.html
|
||||
|
||||
这样写,默认的视图文件就会被替换为你自定义的视图文件,从而实现简单的自定义视图。
|
||||
|
||||
======= 更多资料:
|
||||
|
||||
http://jeesite.com/docs/custom-views/
|
||||
|
||||
Reference in New Issue
Block a user