mirror of https://github.com/halo-dev/halo
✨ 找回密码功能
parent
c2e7bce7bc
commit
f7d40db7b1
|
@ -60,6 +60,10 @@ public class WebMvcAutoConfiguration implements WebMvcConfigurer {
|
|||
.addPathPatterns("/backup/**")
|
||||
.excludePathPatterns("/admin/login")
|
||||
.excludePathPatterns("/admin/getLogin")
|
||||
.excludePathPatterns("/admin/findPassword")
|
||||
.excludePathPatterns("/admin/sendResetPasswordEmail")
|
||||
.excludePathPatterns("/admin/toResetPassword")
|
||||
.excludePathPatterns("/admin/resetPassword")
|
||||
.excludePathPatterns("/static/**");
|
||||
registry.addInterceptor(installInterceptor)
|
||||
.addPathPatterns("/**")
|
||||
|
|
|
@ -13,6 +13,7 @@ import cn.hutool.core.date.DateUnit;
|
|||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.lang.Validator;
|
||||
import cn.hutool.core.text.StrBuilder;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
|
@ -77,6 +78,9 @@ public class AdminController extends BaseController {
|
|||
@Autowired
|
||||
private LocaleMessageUtil localeMessageUtil;
|
||||
|
||||
@Autowired
|
||||
private MailService mailService;
|
||||
|
||||
/**
|
||||
* 请求后台页面
|
||||
*
|
||||
|
@ -193,6 +197,107 @@ public class AdminController extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置密码
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
@GetMapping(value = "/findPassword")
|
||||
public String findPassword() {
|
||||
return "admin/admin_findpassword";
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送重置密码邮件
|
||||
*
|
||||
* @param userName 用户名
|
||||
* @param email 邮箱
|
||||
* @return JsonResult
|
||||
*/
|
||||
@PostMapping(value = "/sendResetPasswordEmail")
|
||||
@ResponseBody
|
||||
public JsonResult sendResetPasswordEmail(@RequestParam(value = "userName") String userName,
|
||||
@RequestParam(value = "email") String email,
|
||||
HttpSession session) {
|
||||
final User user = userService.findUser();
|
||||
if (StrUtil.isEmpty(userName) || StrUtil.isEmpty(email)) {
|
||||
return JsonResult.fail("请输入完整信息!");
|
||||
}
|
||||
if (!user.getUserEmail().equals(email) || !user.getUserName().equals(userName)) {
|
||||
return JsonResult.fail("用户名或电子邮箱错误,请确定你的身份!");
|
||||
}
|
||||
try {
|
||||
long time = System.currentTimeMillis();
|
||||
String randomString = RandomUtil.randomString(10);
|
||||
String code = SecureUtil.md5(time + randomString);
|
||||
StrBuilder url = new StrBuilder(OPTIONS.get(BlogPropertiesEnum.BLOG_URL.getProp()));
|
||||
url.append("/admin/toResetPassword?code=");
|
||||
url.append(code);
|
||||
mailService.sendMail(user.getUserEmail(), "请根据该链接重置你的博客密码", "请点击该链接重置你的密码:" + url);
|
||||
session.setAttribute("resetPasswordCode", code);
|
||||
return JsonResult.success("邮件发送成功,请登录您的邮箱进行下一步操作");
|
||||
} catch (Exception e) {
|
||||
return JsonResult.fail("邮件发送失败,请确定已经配置好了发信服务器信息");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置密码页面
|
||||
*
|
||||
* @param code code
|
||||
* @return String
|
||||
*/
|
||||
@GetMapping(value = "/toResetPassword")
|
||||
public String toResetPassword(@RequestParam(value = "code", defaultValue = "") String code,
|
||||
Model model,
|
||||
HttpSession session) {
|
||||
final String sessionCode = (String) session.getAttribute("resetPasswordCode");
|
||||
if (StrUtil.isEmpty(code)) {
|
||||
this.renderNotFound();
|
||||
}
|
||||
if (!sessionCode.equals(code)) {
|
||||
model.addAttribute("isRight", false);
|
||||
} else {
|
||||
model.addAttribute("isRight", true);
|
||||
}
|
||||
model.addAttribute("code", code);
|
||||
return "admin/admin_resetpassword";
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置密码
|
||||
*
|
||||
* @param password password
|
||||
* @param definePassword definePassword
|
||||
* @return String
|
||||
*/
|
||||
@PostMapping(value = "/resetPassword")
|
||||
@ResponseBody
|
||||
public JsonResult resetPassword(@RequestParam(value = "password") String password,
|
||||
@RequestParam(value = "definePassword") String definePassword,
|
||||
@RequestParam(value = "code") String code,
|
||||
HttpSession session) {
|
||||
final String sessionCode = (String) session.getAttribute("resetPasswordCode");
|
||||
if (null == sessionCode) {
|
||||
return JsonResult.fail("不允许该操作!");
|
||||
}
|
||||
if (!StrUtil.equals(code, sessionCode)) {
|
||||
return JsonResult.fail("不允许该操作!");
|
||||
}
|
||||
if (StrUtil.isEmpty(password) || StrUtil.isEmpty(definePassword)) {
|
||||
return JsonResult.fail("请输入完整信息!");
|
||||
}
|
||||
if (!StrUtil.equals(password, definePassword)) {
|
||||
return JsonResult.fail("两次密码不一样!");
|
||||
}
|
||||
final User user = userService.findUser();
|
||||
user.setUserPass(SecureUtil.md5(password));
|
||||
userService.update(user);
|
||||
userService.updateUserNormal();
|
||||
session.removeAttribute("resetPasswordCode");
|
||||
return JsonResult.success("重置密码成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录 销毁session
|
||||
*
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
<#compress >
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
|
||||
<title>${options.blog_title!} | 找回密码</title>
|
||||
<link rel="stylesheet" href="/static/halo-backend/plugins/bootstrap/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="/static/halo-backend/plugins/animate/animate.min.css">
|
||||
<link rel="stylesheet" href="/static/halo-backend/plugins/toast/css/jquery.toast.min.css">
|
||||
<link rel="stylesheet" href="/static/halo-backend/css/style.min.css">
|
||||
<style>
|
||||
body {
|
||||
background-color: #f5f5f5
|
||||
}
|
||||
|
||||
* {
|
||||
outline: 0
|
||||
}
|
||||
|
||||
label {
|
||||
color: #4b1c0f
|
||||
}
|
||||
|
||||
.findPasswordForm {
|
||||
max-width: 380px;
|
||||
margin-top: 10%
|
||||
}
|
||||
|
||||
.findPasswordLogo {
|
||||
font-size: 56px;
|
||||
text-align: center;
|
||||
margin-bottom: 25px;
|
||||
font-weight: 500;
|
||||
color: #444;
|
||||
text-shadow: #b2baba .1em .1em .2em
|
||||
}
|
||||
|
||||
.findPasswordBody {
|
||||
padding: 20px;
|
||||
background-color: #fff;
|
||||
-o-box-shadow: -4px 7px 46px 2px rgba(0,0,0,.1);
|
||||
box-shadow: -4px 7px 46px 2px rgba(0,0,0,.1)
|
||||
}
|
||||
|
||||
.alert{
|
||||
-o-box-shadow: -4px 7px 46px 2px rgba(0,0,0,.1);
|
||||
box-shadow: -4px 7px 46px 2px rgba(0,0,0,.1)
|
||||
}
|
||||
|
||||
.send-button {
|
||||
background-color: #fff;
|
||||
border-radius: 0;
|
||||
border: 1px solid #000;
|
||||
transition: all .5s ease-in-out
|
||||
}
|
||||
|
||||
.send-button:hover {
|
||||
border: 1px solid #fff;
|
||||
background-color: #000;
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
#userName,#email {
|
||||
border-radius: 0
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container findPasswordForm">
|
||||
<div class="findPasswordLogo animated fadeInUp">
|
||||
Halo <small style="font-size: 14px;">找回密码</small>
|
||||
</div>
|
||||
<div class="alert alert-info animated fadeInUp" role="alert" style="animation-delay: 0.1s">
|
||||
请输入您的用户名和电子邮箱地址。您会收到一封包含创建新密码链接的电子邮件(请确定已经配置好了发信服务器信息)。
|
||||
</div>
|
||||
<div class="findPasswordBody animated">
|
||||
<form>
|
||||
<div class="form-group animated fadeInUp" style="animation-delay: 0.2s">
|
||||
<input type="text" class="form-control" name="userName" id="userName" placeholder="用户名">
|
||||
</div>
|
||||
<div class="form-group animated fadeInUp" style="animation-delay: 0.3s">
|
||||
<input type="text" class="form-control" name="email" id="email" placeholder="电子邮箱地址">
|
||||
</div>
|
||||
<button type="button" id="btnFindPassword" data-loading-text="发送中..." onclick="findPassword()" class="btn btn-block send-button animated fadeInUp" style="animation-delay: 0.4s;outline: none;">发送邮件</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script src="/static/halo-common/jquery/jquery.min.js"></script>
|
||||
<script src="/static/halo-backend/plugins/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script src="/static/halo-backend/plugins/toast/js/jquery.toast.min.js"></script>
|
||||
<script src="/static/halo-backend/js/halo.min.js"></script>
|
||||
<script>
|
||||
var halo = new $.halo();
|
||||
var heading = "<@spring.message code='common.text.tips' />";
|
||||
function findPassword() {
|
||||
var btnFindPassword = $('#btnFindPassword');
|
||||
var name = $("#userName");
|
||||
var email = $("#email");
|
||||
btnFindPassword.button('loading');
|
||||
if (email.val() === "" || name.val() === "") {
|
||||
halo.showMsg("请输入完整信息!", 'info', 2000);
|
||||
btnFindPassword.button('reset');
|
||||
} else {
|
||||
$.post('/admin/sendResetPasswordEmail',{
|
||||
'userName': name.val(),
|
||||
'email': email.val()
|
||||
},function (data) {
|
||||
if (data.code === 1) {
|
||||
halo.showMsgAndRedirect(data.msg,'success',1000,"/admin/login")
|
||||
} else {
|
||||
halo.showMsg(data.msg,'error',2000);
|
||||
}
|
||||
btnFindPassword.button('reset');
|
||||
},'JSON');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</html>
|
||||
</#compress>
|
|
@ -11,7 +11,7 @@
|
|||
<link rel="stylesheet" href="/static/halo-backend/plugins/toast/css/jquery.toast.min.css">
|
||||
<link rel="stylesheet" href="/static/halo-backend/css/style.min.css">
|
||||
<style>
|
||||
body{background-color:#f5f5f5}*{outline:0}label{color:#4b1c0f}.loginForm{max-width:380px;margin-top:10%}.loginLogo{font-size:56px;text-align:center;margin-bottom:25px;font-weight:500;color:#444;text-shadow:#b2baba .1em .1em .2em}.loginBody{padding:20px;background-color:#fff;-o-box-shadow:-4px 7px 46px 2px rgba(0,0,0,.1);box-shadow:-4px 7px 46px 2px rgba(0,0,0,.1)}.login-button{background-color:#fff;border-radius:0;border:1px solid #000;transition:all .5s ease-in-out}.login-button:hover{border:1px solid #fff;background-color:#000;color:#fff}.form-group{padding-bottom:25px}#loginName,#loginPwd{border-radius:0}.control{padding-bottom:5px}
|
||||
body{background-color:#f5f5f5}*{outline:0}label{color:#4b1c0f}.loginForm{max-width:380px;margin-top:10%}.loginLogo{font-size:56px;text-align:center;margin-bottom:25px;font-weight:500;color:#444;text-shadow:#b2baba .1em .1em .2em}.loginBody{padding:20px;background-color:#fff;-o-box-shadow:-4px 7px 46px 2px rgba(0,0,0,.1);box-shadow:-4px 7px 46px 2px rgba(0,0,0,.1)}.login-button{background-color:#fff;border-radius:0;border:1px solid #000;transition:all .5s ease-in-out}.login-button:hover{border:1px solid #fff;background-color:#000;color:#fff}.form-group{margin-bottom: 24px;}#loginName,#loginPwd{border-radius:0}.control{padding-bottom:5px}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -28,14 +28,11 @@
|
|||
<div class="form-group animated fadeInUp" style="animation-delay: 0.2s">
|
||||
<input type="password" class="form-control" name="loginPwd" id="loginPwd" placeholder="<@spring.message code='login.form.loginPwd' />" autocomplete="current-password">
|
||||
</div>
|
||||
<#--<div class="row control animated fadeInUp" style="animation-delay: 0.3s">-->
|
||||
<#--<div class="col-xs-6">-->
|
||||
<#--<label for="remember"><input type="checkbox" id="remember"> <span style="color: #000;font-weight: lighter">记住我</span></label>-->
|
||||
<#--</div>-->
|
||||
<#--<div class="col-xs-6 pull-right text-right">-->
|
||||
<#--<a href="#" style="color: #000;">忘记密码?</a>-->
|
||||
<#--</div>-->
|
||||
<#--</div>-->
|
||||
<div class="row control animated fadeInUp" style="animation-delay: 0.3s">
|
||||
<div class="col-xs-6 pull-right text-right">
|
||||
<a href="/admin/findPassword" style="color: #000;">忘记密码?</a>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" id="btnLogin" data-loading-text="<@spring.message code='login.btn.logining' />" class="btn btn-block login-button animated fadeInUp" onclick="doLogin()" style="animation-delay: 0.4s;outline: none;"><@spring.message code='login.btn.login' /></button>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
<#compress >
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
|
||||
<title>${options.blog_title!} | 重置密码</title>
|
||||
<link rel="stylesheet" href="/static/halo-backend/plugins/bootstrap/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="/static/halo-backend/plugins/animate/animate.min.css">
|
||||
<link rel="stylesheet" href="/static/halo-backend/plugins/toast/css/jquery.toast.min.css">
|
||||
<link rel="stylesheet" href="/static/halo-backend/css/style.min.css">
|
||||
<style>
|
||||
body {
|
||||
background-color: #f5f5f5
|
||||
}
|
||||
|
||||
* {
|
||||
outline: 0
|
||||
}
|
||||
|
||||
label {
|
||||
color: #4b1c0f
|
||||
}
|
||||
|
||||
.findPasswordForm {
|
||||
max-width: 380px;
|
||||
margin-top: 10%
|
||||
}
|
||||
|
||||
.findPasswordLogo {
|
||||
font-size: 56px;
|
||||
text-align: center;
|
||||
margin-bottom: 25px;
|
||||
font-weight: 500;
|
||||
color: #444;
|
||||
text-shadow: #b2baba .1em .1em .2em
|
||||
}
|
||||
|
||||
.findPasswordBody {
|
||||
padding: 20px;
|
||||
background-color: #fff;
|
||||
-o-box-shadow: -4px 7px 46px 2px rgba(0,0,0,.1);
|
||||
box-shadow: -4px 7px 46px 2px rgba(0,0,0,.1)
|
||||
}
|
||||
|
||||
.alert{
|
||||
-o-box-shadow: -4px 7px 46px 2px rgba(0,0,0,.1);
|
||||
box-shadow: -4px 7px 46px 2px rgba(0,0,0,.1)
|
||||
}
|
||||
|
||||
.reset-button {
|
||||
background-color: #fff;
|
||||
border-radius: 0;
|
||||
border: 1px solid #000;
|
||||
transition: all .5s ease-in-out
|
||||
}
|
||||
|
||||
.reset-button:hover {
|
||||
border: 1px solid #fff;
|
||||
background-color: #000;
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
#password,#definePassword {
|
||||
border-radius: 0
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container findPasswordForm">
|
||||
<div class="findPasswordLogo animated fadeInUp">
|
||||
Halo <small style="font-size: 14px;">重置密码</small>
|
||||
</div>
|
||||
<#if isRight>
|
||||
<div class="findPasswordBody animated">
|
||||
<form>
|
||||
<div class="form-group animated fadeInUp" style="animation-delay: 0.1s">
|
||||
<input type="password" class="form-control" name="password" id="password" placeholder="新密码">
|
||||
</div>
|
||||
<div class="form-group animated fadeInUp" style="animation-delay: 0.2s">
|
||||
<input type="password" class="form-control" name="definePassword" id="definePassword" placeholder="确认新密码">
|
||||
</div>
|
||||
<button type="button" id="btnResetPassword" onclick="resetPassword()" class="btn btn-block reset-button animated fadeInUp" style="animation-delay: 0.3s;outline: none;">重置密码</button>
|
||||
</form>
|
||||
</div>
|
||||
<#else>
|
||||
<div class="alert alert-info animated fadeInUp" role="alert" style="animation-delay: 0.1s">该链接已失效,请重新上一步操作</div>
|
||||
</#if>
|
||||
</div>
|
||||
</body>
|
||||
<#if isRight>
|
||||
<script src="/static/halo-common/jquery/jquery.min.js"></script>
|
||||
<script src="/static/halo-backend/plugins/bootstrap/js/bootstrap.min.js"></script>
|
||||
<script src="/static/halo-backend/plugins/toast/js/jquery.toast.min.js"></script>
|
||||
<script src="/static/halo-backend/js/halo.min.js"></script>
|
||||
<script>
|
||||
var halo = new $.halo();
|
||||
var heading = "<@spring.message code='common.text.tips' />";
|
||||
function resetPassword() {
|
||||
var password = $('#password');
|
||||
var definePassword = $('#definePassword');
|
||||
if (password.val() === "" || definePassword.val() === "") {
|
||||
halo.showMsg("请输入完整信息!", 'info', 2000);
|
||||
} else {
|
||||
$.post('/admin/resetPassword',{
|
||||
'password': password.val(),
|
||||
'definePassword': definePassword.val(),
|
||||
'code': '${code}'
|
||||
},function (data) {
|
||||
if (data.code === 1) {
|
||||
halo.showMsgAndRedirect(data.msg,'success',1000,"/admin/login")
|
||||
} else {
|
||||
halo.showMsg(data.msg,'error',2000);
|
||||
}
|
||||
},'JSON');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</#if>
|
||||
</html>
|
||||
</#compress>
|
Loading…
Reference in New Issue