This commit is contained in:
MaxKey
2021-08-04 23:40:20 +08:00
parent 3f9e4960c7
commit 9d81e0cbbb
16 changed files with 350 additions and 267 deletions

View File

@@ -17,9 +17,13 @@
package org.maxkey;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;
import org.maxkey.authn.realm.jdbc.JdbcAuthenticationRealm;
import org.maxkey.authn.realm.ldap.LdapAuthenticationRealm;
@@ -31,6 +35,7 @@ import org.maxkey.authn.realm.activedirectory.ActiveDirectoryServer;
import org.maxkey.authn.support.kerberos.KerberosProxy;
import org.maxkey.authn.support.kerberos.RemoteKerberosService;
import org.maxkey.authn.support.rememberme.AbstractRemeberMeService;
import org.maxkey.configuration.EmailConfig;
import org.maxkey.constants.ConstantsPersistence;
import org.maxkey.constants.ConstantsProperties;
import org.maxkey.password.onetimepwd.AbstractOtpAuthn;
@@ -57,6 +62,8 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
@@ -216,14 +223,32 @@ public class MaxKeyConfig implements InitializingBean {
@Bean(name = "mailOtpAuthn")
public MailOtpAuthn mailOtpAuthn(
EmailConfig emailConfig,
@Value("${spring.mail.properties.mailotp.message.subject}")
String messageSubject,
@Value("${spring.mail.properties.mailotp.message.template}")
String messageTemplate
String messageTemplate,
@Value("${spring.mail.properties.mailotp.message.validity}")
int messageValidity,
@Value("${spring.mail.properties.mailotp.message.type}")
String messageType
) {
if(messageType!= null && messageType.equalsIgnoreCase("html")) {
Resource resource = new ClassPathResource("messages/email/forgotpassword.html");
try {
BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(resource.getInputStream()));
messageTemplate = bufferedReader.lines().collect(Collectors.joining("\n"));
bufferedReader.close();
} catch (IOException e) {
_logger.error("mailOtpAuthn IOException ",e);
}
}
_logger.trace("messageTemplate \n" +messageTemplate);
MailOtpAuthn mailOtpAuthn = new MailOtpAuthn();
mailOtpAuthn.setSubject(messageSubject);
mailOtpAuthn.setMessageTemplate(messageTemplate);
mailOtpAuthn.setEmailConfig(emailConfig);
mailOtpAuthn.setInterval(messageValidity);
_logger.debug("MailOtpAuthn inited.");
return mailOtpAuthn;
}

View File

@@ -17,11 +17,12 @@
package org.maxkey.web.contorller;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.maxkey.configuration.EmailConfig;
import org.maxkey.entity.UserInfo;
import org.maxkey.password.onetimepwd.AbstractOtpAuthn;
import org.maxkey.persistence.db.PasswordPolicyValidator;
import org.maxkey.persistence.service.UserInfoService;
import org.maxkey.web.WebConstants;
import org.maxkey.web.WebContext;
@@ -45,6 +46,9 @@ public class ForgotPasswordContorller {
Pattern mobileRegex = Pattern.compile(
"^(13[4,5,6,7,8,9]|15[0,8,9,1,7]|188|187)\\\\d{8}$");
@Autowired
EmailConfig emailConfig;
public class ForgotType{
public final static int NOTFOUND = 1;
public final static int EMAIL = 2;
@@ -84,16 +88,24 @@ public class ForgotPasswordContorller {
UserInfo userInfo = null;
if (captcha != null && captcha
.equals(WebContext.getSession().getAttribute(
WebConstants.KAPTCHA_SESSION_KEY).toString())) {
WebConstants.KAPTCHA_SESSION_KEY).toString())) {
if(mobileRegex.matcher(emailMobile).matches()) {
forgotType = ForgotType.MOBILE;
}else if(emailRegex.matcher(emailMobile).matches()) {
forgotType = ForgotType.EMAIL;
}else {
forgotType = ForgotType.EMAIL;
emailMobile =emailMobile + "@" + emailConfig.getSmtpHost().substring(emailConfig.getSmtpHost().indexOf(".")+1);
}
userInfo = userInfoService.queryUserInfoByEmailMobile(emailMobile);
Matcher matcher = emailRegex.matcher(emailMobile);
if (matcher.matches() && null != userInfo) {
mailOtpAuthn.produce(userInfo);
forgotType = ForgotType.EMAIL;
}else if (null != userInfo) {
smsOtpAuthn.produce(userInfo);
forgotType = ForgotType.MOBILE;
if(null != userInfo) {
if (forgotType == ForgotType.EMAIL ) {
mailOtpAuthn.produce(userInfo);
}else if (forgotType == ForgotType.MOBILE) {
smsOtpAuthn.produce(userInfo);
}
}
}else {
@@ -129,8 +141,13 @@ public class ForgotPasswordContorller {
if ((forgotType == ForgotType.EMAIL && mailOtpAuthn.validate(userInfo, captcha)) ||
(forgotType == ForgotType.MOBILE && smsOtpAuthn.validate(userInfo, captcha))
) {
userInfoService.changePassword(userInfo,true);
modelAndView.addObject("passwordResetResult", PasswordResetResult.SUCCESS);
if(userInfoService.changePassword(userInfo,true)) {
modelAndView.addObject("passwordResetResult", PasswordResetResult.SUCCESS);
}else {
;
modelAndView.addObject("validate_result", WebContext.getAttribute(PasswordPolicyValidator.PASSWORD_POLICY_VALIDATE_RESULT));
modelAndView.addObject("passwordResetResult", PasswordResetResult.PASSWORDERROR);
}
} else {
modelAndView.addObject("passwordResetResult", PasswordResetResult.CAPTCHAERROR);
}

View File

@@ -23,6 +23,7 @@ import org.apache.mybatis.jpa.persistence.JpaPageResults;
import org.maxkey.entity.HistoryLoginApps;
import org.maxkey.persistence.service.HistoryLoginAppsService;
import org.maxkey.util.DateUtils;
import org.maxkey.web.WebContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -66,7 +67,7 @@ public class HistoryLoginAppsController {
@ModelAttribute("historyLoginApps") HistoryLoginApps historyLoginApps) {
_logger.debug("history/loginApps/grid/ logsGrid() " + historyLoginApps);
historyLoginApps.setId(null);
historyLoginApps.setUsername(WebContext.getUserInfo().getUsername());
return historyLoginAppsService.queryPageResults(historyLoginApps);
}

View File

@@ -95,7 +95,8 @@ mybatis.table-column-case=lowercase
#spring.mail.properties.sender=maxkey@163.com
spring.mail.properties.mailotp.message.subject=MaxKey One Time PassWord
spring.mail.properties.mailotp.message.template={0} You Token is {1} , it validity in {2} minutes.
spring.mail.properties.mailotp.message.type=html
spring.mail.properties.mailotp.message.validity=300
############################################################################
#freemarker configuration #
############################################################################
@@ -139,23 +140,20 @@ spring.session.store-type=none
#Kafka for connectors configuration #
############################################################################
spring.kafka.bootstrap-servers=localhost:9092
###########\u3010\u521d\u59cb\u5316\u751f\u4ea7\u8005\u914d\u7f6e\u3011###########
# \u91cd\u8bd5\u6b21\u6570
# retries
spring.kafka.producer.retries=0
# \u5e94\u7b54\u7ea7\u522b:\u591a\u5c11\u4e2a\u5206\u533a\u526f\u672c\u5907\u4efd\u5b8c\u6210\u65f6\u5411\u751f\u4ea7\u8005\u53d1\u9001ack\u786e\u8ba4(\u53ef\u90090\u30011\u3001all/-1)
# acks
spring.kafka.producer.acks=1
# \u6279\u91cf\u5927\u5c0f
# batch-size
spring.kafka.producer.batch-size=16384
# \u63d0\u4ea4\u5ef6\u65f6
# linger.ms
spring.kafka.producer.properties.linger.ms=0
# \u5f53\u751f\u4ea7\u7aef\u79ef\u7d2f\u7684\u6d88\u606f\u8fbe\u5230batch-size\u6216\u63a5\u6536\u5230\u6d88\u606flinger.ms\u540e,\u751f\u4ea7\u8005\u5c31\u4f1a\u5c06\u6d88\u606f\u63d0\u4ea4\u7ed9kafka
# linger.ms\u4e3a0\u8868\u793a\u6bcf\u63a5\u6536\u5230\u4e00\u6761\u6d88\u606f\u5c31\u63d0\u4ea4\u7ed9kafka,\u8fd9\u65f6\u5019batch-size\u5176\u5b9e\u5c31\u6ca1\u7528\u4e86
# \u751f\u4ea7\u7aef\u7f13\u51b2\u533a\u5927\u5c0f
# buffer-memory
spring.kafka.producer.buffer-memory = 33554432
# Kafka\u63d0\u4f9b\u7684\u5e8f\u5217\u5316\u548c\u53cd\u5e8f\u5217\u5316\u7c7b
# serializer
spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer
# \u81ea\u5b9a\u4e49\u5206\u533a\u5668
# partitioner
# spring.kafka.producer.properties.partitioner.class=com.felix.kafka.producer.CustomizePartitioner
############################################################################

View File

@@ -95,6 +95,8 @@ mybatis.table-column-case=lowercase
#spring.mail.properties.sender=maxkey@163.com
spring.mail.properties.mailotp.message.subject=MaxKey One Time PassWord
spring.mail.properties.mailotp.message.template={0} You Token is {1} , it validity in {2} minutes.
spring.mail.properties.mailotp.message.type=html
spring.mail.properties.mailotp.message.validity=300
############################################################################
#freemarker configuration #
@@ -139,24 +141,21 @@ spring.session.store-type=none
#Kafka for connectors configuration #
############################################################################
spring.kafka.bootstrap-servers=localhost:9092
###########\u3010\u521d\u59cb\u5316\u751f\u4ea7\u8005\u914d\u7f6e\u3011###########
# \u91cd\u8bd5\u6b21\u6570
# retries
spring.kafka.producer.retries=0
# \u5e94\u7b54\u7ea7\u522b:\u591a\u5c11\u4e2a\u5206\u533a\u526f\u672c\u5907\u4efd\u5b8c\u6210\u65f6\u5411\u751f\u4ea7\u8005\u53d1\u9001ack\u786e\u8ba4(\u53ef\u90090\u30011\u3001all/-1)
# acks
spring.kafka.producer.acks=1
# \u6279\u91cf\u5927\u5c0f
# batch-size
spring.kafka.producer.batch-size=16384
# \u63d0\u4ea4\u5ef6\u65f6
# linger.ms
spring.kafka.producer.properties.linger.ms=0
# \u5f53\u751f\u4ea7\u7aef\u79ef\u7d2f\u7684\u6d88\u606f\u8fbe\u5230batch-size\u6216\u63a5\u6536\u5230\u6d88\u606flinger.ms\u540e,\u751f\u4ea7\u8005\u5c31\u4f1a\u5c06\u6d88\u606f\u63d0\u4ea4\u7ed9kafka
# linger.ms\u4e3a0\u8868\u793a\u6bcf\u63a5\u6536\u5230\u4e00\u6761\u6d88\u606f\u5c31\u63d0\u4ea4\u7ed9kafka,\u8fd9\u65f6\u5019batch-size\u5176\u5b9e\u5c31\u6ca1\u7528\u4e86
# \u751f\u4ea7\u7aef\u7f13\u51b2\u533a\u5927\u5c0f
# buffer-memory
spring.kafka.producer.buffer-memory = 33554432
# Kafka\u63d0\u4f9b\u7684\u5e8f\u5217\u5316\u548c\u53cd\u5e8f\u5217\u5316\u7c7b
# serializer
spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer
# \u81ea\u5b9a\u4e49\u5206\u533a\u5668
# spring.kafka.producer.properties.partitioner.class=com.felix.kafka.producer.CustomizePartitioner
# partitioner
#spring.kafka.producer.properties.partitioner.class=com.felix.kafka.producer.CustomizePartitioner
############################################################################
#Management endpoints configuration #
@@ -366,7 +365,7 @@ maxkey.socialsignon.wechatopen.sortorder=2
#work weixin
maxkey.socialsignon.workweixin.provider=workweixin
maxkey.socialsignon.workweixin.provider.name=\u4F01\u4E1A\u5fae\u4fe1
maxkey.socialsignon.workweixin.icon=images/social/wechat.png
maxkey.socialsignon.workweixin.icon=images/social/wechat_enterprise.png
maxkey.socialsignon.workweixin.client.id=wx00d052e8f417f8f9
maxkey.socialsignon.workweixin.client.secret=lIy40iP0z4D65eJaWDNoe-vSlttmqY2WGJBygbM0TlY
maxkey.socialsignon.workweixin.agent.id=1000002

View File

@@ -0,0 +1,5 @@
尊敬的用户{0}<br>
请复制下面的验证码并返回页面提交以继续之前的步骤 <br>
<p><b>{1}</b></p>
有效期为{2}分钟.<br>
如果您没有申请发送该邮件请忽略

View File

@@ -218,8 +218,12 @@ button.text.expandsearch=\u5c55\u5f00
button.text.collapsesearch=\u6536\u7f29
forgotpassword.emailmobile=\u90ae\u7bb1\u6216\u624b\u673a
forgotpassword.email=\u90ae\u7bb1
forgotpassword.mobile=\u624b\u673a
forgotpassword.nextstep=\u4e0b\u4e00\u6b65
forgotpassword.resetpwd.notfound.prefix=\u90ae\u7bb1\u6216\u624b\u673a\u53f7
forgotpassword.resetpwd.notfound.prefix.email=\u90ae\u7bb1
forgotpassword.resetpwd.notfound.prefix.mobile=\u624b\u673a\u53f7
forgotpassword.resetpwd.notfound.suffix=\u4e0d\u5b58\u5728,\u8bf7
forgotpassword.backstep=\u91cd\u65b0\u8f93\u5165
forgotpassword.pwdreseted.password=\u8f93\u5165\u5bc6\u7801\u6216\u786e\u8ba4\u5bc6\u7801\u9519\u8bef\uff0c\u8bf7

View File

@@ -217,8 +217,12 @@ button.text.expandsearch=Expand
button.text.collapsesearch=Collapse
forgotpassword.emailmobile=Email OR Mobile
forgotpassword.email=Email
forgotpassword.mobile=Mobile
forgotpassword.nextstep=Next
forgotpassword.resetpwd.notfound.prefix=Email OR Mobile
forgotpassword.resetpwd.notfound.prefix.email=Email
forgotpassword.resetpwd.notfound.prefix.mobile=Mobile
forgotpassword.resetpwd.notfound.suffix=not found,pls
forgotpassword.backstep=Retry
forgotpassword.pwdreseted.password=password error or password not eq the confirm password,pls

View File

@@ -218,8 +218,12 @@ button.text.expandsearch=\u5c55\u5f00
button.text.collapsesearch=\u6536\u7f29
forgotpassword.emailmobile=\u90ae\u7bb1\u6216\u624b\u673a
forgotpassword.email=\u90ae\u7bb1
forgotpassword.mobile=\u624b\u673a
forgotpassword.nextstep=\u4e0b\u4e00\u6b65
forgotpassword.resetpwd.notfound.prefix=\u90ae\u7bb1\u6216\u624b\u673a\u53f7
forgotpassword.resetpwd.notfound.prefix.email=\u90ae\u7bb1
forgotpassword.resetpwd.notfound.prefix.mobile=\u624b\u673a\u53f7
forgotpassword.resetpwd.notfound.suffix=\u4e0d\u5b58\u5728,\u8bf7
forgotpassword.backstep=\u91cd\u65b0\u8f93\u5165
forgotpassword.pwdreseted.password=\u8f93\u5165\u5bc6\u7801\u6216\u786e\u8ba4\u5bc6\u7801\u9519\u8bef\uff0c\u8bf7

View File

@@ -15,7 +15,8 @@
<div class="col-md-8">
<#if 3 == passwordResetResult>
<@locale code="forgotpassword.pwdreseted.password"/>
<a href="javascript:history.go(-1);"><@locale code="forgotpassword.backstep"/></a >
<a href="<@base/>/forgotpassword/forward"><@locale code="forgotpassword.backstep"/></a >
<br>${validate_result}
</#if>
<#if 2 == passwordResetResult>