Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
MaxKey单点登录官方(MaxKeyTop)
MaxKey
提交
7ddde380
MaxKey
项目概览
MaxKey单点登录官方(MaxKeyTop)
/
MaxKey
11 个月 前同步成功
通知
76
Star
3
Fork
1
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
MaxKey
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
7ddde380
编写于
4月 25, 2022
作者:
M
MaxKey
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
ForgotPassword
上级
d6856b1f
变更
25
隐藏空白更改
内联
并排
Showing
25 changed file
with
599 addition
and
160 deletion
+599
-160
maxkey-authentications/maxkey-authentication-captcha/src/main/java/org/maxkey/web/contorller/ImageCaptcha.java
...src/main/java/org/maxkey/web/contorller/ImageCaptcha.java
+12
-7
maxkey-authentications/maxkey-authentication-captcha/src/main/java/org/maxkey/web/contorller/ImageCaptchaEndpoint.java
.../java/org/maxkey/web/contorller/ImageCaptchaEndpoint.java
+1
-1
maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/AbstractAuthenticationProvider.java
...java/org/maxkey/authn/AbstractAuthenticationProvider.java
+0
-3
maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/jwt/AuthJwtService.java
...re/src/main/java/org/maxkey/authn/jwt/AuthJwtService.java
+28
-2
maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/provider/MfaAuthenticationProvider.java
.../org/maxkey/authn/provider/MfaAuthenticationProvider.java
+1
-4
maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/provider/NormalAuthenticationProvider.java
...g/maxkey/authn/provider/NormalAuthenticationProvider.java
+3
-18
maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/web/AuthorizationUtils.java
...rc/main/java/org/maxkey/authn/web/AuthorizationUtils.java
+1
-1
maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/autoconfigure/AuthenticationAutoConfiguration.java
...maxkey/autoconfigure/AuthenticationAutoConfiguration.java
+4
-5
maxkey-authentications/maxkey-authentication-otp/src/main/java/org/maxkey/password/onetimepwd/OtpAuthnService.java
.../java/org/maxkey/password/onetimepwd/OtpAuthnService.java
+26
-0
maxkey-core/src/main/java/org/maxkey/entity/ChangePassword.java
...-core/src/main/java/org/maxkey/entity/ChangePassword.java
+5
-0
maxkey-core/src/main/java/org/maxkey/persistence/repository/PasswordPolicyRepository.java
...xkey/persistence/repository/PasswordPolicyRepository.java
+1
-0
maxkey-web-frontend/maxkey-web-app/src/app/app.module.ts
maxkey-web-frontend/maxkey-web-app/src/app/app.module.ts
+1
-1
maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/forgot/forgot.component.html
...-app/src/app/routes/passport/forgot/forgot.component.html
+120
-0
maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/forgot/forgot.component.less
...-app/src/app/routes/passport/forgot/forgot.component.less
+21
-0
maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/forgot/forgot.component.spec.ts
...p/src/app/routes/passport/forgot/forgot.component.spec.ts
+25
-0
maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/forgot/forgot.component.ts
...eb-app/src/app/routes/passport/forgot/forgot.component.ts
+176
-0
maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/login/login.component.html
...eb-app/src/app/routes/passport/login/login.component.html
+1
-1
maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/passport-routing.module.ts
...eb-app/src/app/routes/passport/passport-routing.module.ts
+6
-0
maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/passport.module.ts
...maxkey-web-app/src/app/routes/passport/passport.module.ts
+5
-3
maxkey-web-frontend/maxkey-web-app/src/app/service/forgot-password.service.ts
...maxkey-web-app/src/app/service/forgot-password.service.ts
+20
-0
maxkey-web-frontend/maxkey-web-app/src/assets/i18n/en-US.json
...ey-web-frontend/maxkey-web-app/src/assets/i18n/en-US.json
+17
-0
maxkey-web-frontend/maxkey-web-app/src/assets/i18n/zh-CN.json
...ey-web-frontend/maxkey-web-app/src/assets/i18n/zh-CN.json
+18
-1
maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/contorller/ChangePasswodController.java
...va/org/maxkey/web/contorller/ChangePasswodController.java
+8
-21
maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/contorller/ForgotPasswordContorller.java
...a/org/maxkey/web/contorller/ForgotPasswordContorller.java
+99
-89
maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/contorller/SafeController.java
...c/main/java/org/maxkey/web/contorller/SafeController.java
+0
-3
未找到文件。
maxkey-authentications/maxkey-authentication-captcha/src/main/java/org/maxkey/web/contorller/ImageCaptcha.java
浏览文件 @
7ddde380
...
...
@@ -17,21 +17,26 @@
package
org.maxkey.web.contorller
;
public
class
ImageCaptcha
{
String
id
;
String
state
;
String
image
;
public
ImageCaptcha
(
String
id
,
String
image
)
{
public
ImageCaptcha
(
String
state
,
String
image
)
{
super
();
this
.
id
=
id
;
this
.
state
=
state
;
this
.
image
=
image
;
}
public
String
getId
()
{
return
id
;
public
String
getState
()
{
return
state
;
}
public
void
setId
(
String
id
)
{
this
.
id
=
id
;
public
void
setState
(
String
state
)
{
this
.
state
=
state
;
}
public
String
getImage
()
{
return
image
;
}
...
...
maxkey-authentications/maxkey-authentication-captcha/src/main/java/org/maxkey/web/contorller/ImageCaptchaEndpoint.java
浏览文件 @
7ddde380
...
...
@@ -88,7 +88,7 @@ public class ImageCaptchaEndpoint {
}
else
{
state
=
authJwtService
.
genJwt
();
}
kaptchaKey
=
authJwtService
.
resolve
Ticket
(
state
);
kaptchaKey
=
authJwtService
.
resolve
JWTID
(
state
);
_logger
.
trace
(
"kaptchaKey {} , Captcha Text is {}"
,
kaptchaKey
,
kaptchaValue
);
momentaryService
.
put
(
""
,
kaptchaKey
,
kaptchaValue
);
...
...
maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/AbstractAuthenticationProvider.java
浏览文件 @
7ddde380
...
...
@@ -30,7 +30,6 @@ import org.maxkey.constants.ConstsStatus;
import
org.maxkey.entity.UserInfo
;
import
org.maxkey.password.onetimepwd.AbstractOtpAuthn
;
import
org.maxkey.password.onetimepwd.OtpAuthnService
;
import
org.maxkey.persistence.MomentaryService
;
import
org.maxkey.web.WebConstants
;
import
org.maxkey.web.WebContext
;
import
org.slf4j.Logger
;
...
...
@@ -70,8 +69,6 @@ public abstract class AbstractAuthenticationProvider {
protected
OnlineTicketService
onlineTicketServices
;
protected
MomentaryService
momentaryService
;
protected
AuthJwtService
authJwtService
;
public
static
ArrayList
<
GrantedAuthority
>
grantedAdministratorsAuthoritys
=
new
ArrayList
<
GrantedAuthority
>();
...
...
maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/jwt/AuthJwtService.java
浏览文件 @
7ddde380
...
...
@@ -19,11 +19,14 @@ package org.maxkey.authn.jwt;
import
java.text.ParseException
;
import
java.util.Date
;
import
org.apache.commons.lang3.StringUtils
;
import
org.joda.time.DateTime
;
import
org.maxkey.authn.SigninPrincipal
;
import
org.maxkey.configuration.AuthJwkConfig
;
import
org.maxkey.crypto.jwt.HMAC512Service
;
import
org.maxkey.entity.UserInfo
;
import
org.maxkey.persistence.MomentaryService
;
import
org.maxkey.web.WebContext
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
...
...
@@ -44,6 +47,8 @@ public class AuthJwtService {
AuthJwkConfig
authJwkConfig
;
CongressService
congressService
;
MomentaryService
momentaryService
;
public
AuthJwtService
(
AuthJwkConfig
authJwkConfig
)
throws
JOSEException
{
this
.
authJwkConfig
=
authJwkConfig
;
...
...
@@ -51,12 +56,16 @@ public class AuthJwtService {
this
.
hmac512Service
=
new
HMAC512Service
(
authJwkConfig
.
getSecret
());
}
public
AuthJwtService
(
AuthJwkConfig
authJwkConfig
,
CongressService
congressService
)
throws
JOSEException
{
public
AuthJwtService
(
AuthJwkConfig
authJwkConfig
,
CongressService
congressService
,
MomentaryService
momentaryService
)
throws
JOSEException
{
this
.
authJwkConfig
=
authJwkConfig
;
this
.
congressService
=
congressService
;
this
.
momentaryService
=
momentaryService
;
this
.
hmac512Service
=
new
HMAC512Service
(
authJwkConfig
.
getSecret
());
}
/**
...
...
@@ -156,7 +165,7 @@ public class AuthJwtService {
return
signedJWT
.
getJWTClaimsSet
();
}
public
String
resolve
Ticket
(
String
authToken
)
throws
ParseException
{
public
String
resolve
JWTID
(
String
authToken
)
throws
ParseException
{
JWTClaimsSet
claims
=
resolve
(
authToken
);
return
claims
.
getJWTID
();
}
...
...
@@ -177,4 +186,21 @@ public class AuthJwtService {
return
authJwt
;
}
public
boolean
validateCaptcha
(
String
state
,
String
captcha
)
{
try
{
String
jwtId
=
resolveJWTID
(
state
);
if
(
StringUtils
.
isNotBlank
(
jwtId
)
&&
StringUtils
.
isNotBlank
(
captcha
))
{
Object
momentaryCaptcha
=
momentaryService
.
get
(
""
,
jwtId
);
_logger
.
debug
(
"captcha : {}, momentary Captcha : {}"
,
captcha
,
momentaryCaptcha
);
if
(!
StringUtils
.
isBlank
(
captcha
)
&&
captcha
.
equals
(
momentaryCaptcha
.
toString
()))
{
momentaryService
.
remove
(
""
,
jwtId
);
return
true
;
}
}
}
catch
(
ParseException
e
)
{
_logger
.
debug
(
"Exception "
,
e
);
}
return
false
;
}
}
maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/provider/MfaAuthenticationProvider.java
浏览文件 @
7ddde380
...
...
@@ -26,7 +26,6 @@ import org.maxkey.configuration.ApplicationConfig;
import
org.maxkey.constants.ConstsLoginType
;
import
org.maxkey.entity.Institutions
;
import
org.maxkey.entity.UserInfo
;
import
org.maxkey.persistence.MomentaryService
;
import
org.maxkey.web.WebConstants
;
import
org.maxkey.web.WebContext
;
import
org.slf4j.Logger
;
...
...
@@ -59,13 +58,11 @@ public class MfaAuthenticationProvider extends AbstractAuthenticationProvider {
AbstractAuthenticationRealm
authenticationRealm
,
ApplicationConfig
applicationConfig
,
OnlineTicketService
onlineTicketServices
,
AuthJwtService
authJwtService
,
MomentaryService
momentaryService
)
{
AuthJwtService
authJwtService
)
{
this
.
authenticationRealm
=
authenticationRealm
;
this
.
applicationConfig
=
applicationConfig
;
this
.
onlineTicketServices
=
onlineTicketServices
;
this
.
authJwtService
=
authJwtService
;
this
.
momentaryService
=
momentaryService
;
}
@Override
...
...
maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/provider/NormalAuthenticationProvider.java
浏览文件 @
7ddde380
...
...
@@ -18,7 +18,6 @@
package
org.maxkey.authn.provider
;
import
java.text.ParseException
;
import
org.apache.commons.lang3.StringUtils
;
import
org.maxkey.authn.AbstractAuthenticationProvider
;
import
org.maxkey.authn.LoginCredential
;
import
org.maxkey.authn.jwt.AuthJwtService
;
...
...
@@ -28,7 +27,6 @@ import org.maxkey.configuration.ApplicationConfig;
import
org.maxkey.constants.ConstsLoginType
;
import
org.maxkey.entity.Institutions
;
import
org.maxkey.entity.UserInfo
;
import
org.maxkey.persistence.MomentaryService
;
import
org.maxkey.web.WebConstants
;
import
org.maxkey.web.WebContext
;
import
org.slf4j.Logger
;
...
...
@@ -60,13 +58,11 @@ public class NormalAuthenticationProvider extends AbstractAuthenticationProvider
AbstractAuthenticationRealm
authenticationRealm
,
ApplicationConfig
applicationConfig
,
OnlineTicketService
onlineTicketServices
,
AuthJwtService
authJwtService
,
MomentaryService
momentaryService
)
{
AuthJwtService
authJwtService
)
{
this
.
authenticationRealm
=
authenticationRealm
;
this
.
applicationConfig
=
applicationConfig
;
this
.
onlineTicketServices
=
onlineTicketServices
;
this
.
authJwtService
=
authJwtService
;
this
.
momentaryService
=
momentaryService
;
}
@Override
...
...
@@ -138,19 +134,8 @@ public class NormalAuthenticationProvider extends AbstractAuthenticationProvider
*/
protected
void
captchaValid
(
String
state
,
String
captcha
)
throws
ParseException
{
// for basic
String
ticket
=
authJwtService
.
resolveTicket
(
state
);
if
(
ticket
==
null
)
{
if
(!
authJwtService
.
validateCaptcha
(
state
,
captcha
))
{
throw
new
BadCredentialsException
(
WebContext
.
getI18nValue
(
"login.error.captcha"
));
}
Object
momentaryCaptcha
=
momentaryService
.
get
(
""
,
ticket
);
_logger
.
info
(
"captcha : {} , momentary Captcha : {} "
,
captcha
,
momentaryCaptcha
);
if
(
StringUtils
.
isBlank
(
captcha
)
||
!
captcha
.
equals
(
momentaryCaptcha
.
toString
()))
{
_logger
.
debug
(
"login captcha valid error."
);
throw
new
BadCredentialsException
(
WebContext
.
getI18nValue
(
"login.error.captcha"
));
}
momentaryService
.
remove
(
""
,
ticket
);
}
}
}
maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/web/AuthorizationUtils.java
浏览文件 @
7ddde380
...
...
@@ -73,7 +73,7 @@ public class AuthorizationUtils {
AuthJwtService
authJwtService
,
OnlineTicketService
onlineTicketService
)
throws
ParseException
{
if
(
authJwtService
.
validateJwtToken
(
authorization
))
{
String
ticket
=
authJwtService
.
resolve
Ticket
(
authorization
);
String
ticket
=
authJwtService
.
resolve
JWTID
(
authorization
);
OnlineTicket
onlineTicket
=
onlineTicketService
.
get
(
ticket
);
if
(
onlineTicket
!=
null
)
{
setAuthentication
(
onlineTicket
.
getAuthentication
());
...
...
maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/autoconfigure/AuthenticationAutoConfiguration.java
浏览文件 @
7ddde380
...
...
@@ -87,16 +87,14 @@ public class AuthenticationAutoConfiguration implements InitializingBean {
AbstractAuthenticationRealm
authenticationRealm
,
ApplicationConfig
applicationConfig
,
OnlineTicketService
onlineTicketServices
,
AuthJwtService
authJwtService
,
MomentaryService
momentaryService
AuthJwtService
authJwtService
)
{
_logger
.
debug
(
"init authentication Provider ."
);
return
new
NormalAuthenticationProvider
(
authenticationRealm
,
applicationConfig
,
onlineTicketServices
,
authJwtService
,
momentaryService
authJwtService
);
}
...
...
@@ -134,6 +132,7 @@ public class AuthenticationAutoConfiguration implements InitializingBean {
public
AuthJwtService
authJwtService
(
AuthJwkConfig
authJwkConfig
,
RedisConnectionFactory
redisConnFactory
,
MomentaryService
momentaryService
,
@Value
(
"${maxkey.server.persistence}"
)
int
persistence
)
throws
JOSEException
{
CongressService
congressService
;
if
(
persistence
==
ConstsPersistence
.
REDIS
)
{
...
...
@@ -142,7 +141,7 @@ public class AuthenticationAutoConfiguration implements InitializingBean {
congressService
=
new
InMemoryCongressService
();
}
AuthJwtService
authJwtService
=
new
AuthJwtService
(
authJwkConfig
,
congressService
);
AuthJwtService
authJwtService
=
new
AuthJwtService
(
authJwkConfig
,
congressService
,
momentaryService
);
return
authJwtService
;
}
...
...
maxkey-authentications/maxkey-authentication-otp/src/main/java/org/maxkey/password/onetimepwd/OtpAuthnService.java
浏览文件 @
7ddde380
...
...
@@ -124,6 +124,32 @@ public class OtpAuthnService {
}
return
otpAuthn
;
}
public
AbstractOtpAuthn
getMailOtpAuthn
(
String
instId
)
{
AbstractOtpAuthn
otpAuthn
=
otpAuthnStore
.
getIfPresent
(
instId
);
if
(
otpAuthn
==
null
)
{
EmailSenders
emailSender
=
emailSendersService
.
findOne
(
"where instid = ? "
,
new
Object
[]{
instId
},
new
int
[]{
Types
.
VARCHAR
});
String
credentials
=
PasswordReciprocal
.
getInstance
().
decoder
(
emailSender
.
getCredentials
());
EmailConfig
emailConfig
=
new
EmailConfig
(
emailSender
.
getAccount
(),
credentials
,
emailSender
.
getSmtpHost
(),
emailSender
.
getPort
(),
ConstsBoolean
.
isTrue
(
emailSender
.
getSslSwitch
()),
emailSender
.
getSender
());
MailOtpAuthn
mailOtpAuthn
=
new
MailOtpAuthn
(
emailConfig
);
mailOtpAuthn
.
setInterval
(
60
*
5
);
//5 minute
if
(
redisOptTokenStore
!=
null
)
{
mailOtpAuthn
.
setOptTokenStore
(
redisOptTokenStore
);
}
otpAuthn
=
mailOtpAuthn
;
}
otpAuthnStore
.
put
(
instId
,
otpAuthn
);
return
otpAuthn
;
}
public
void
setRedisOptTokenStore
(
RedisOtpTokenStore
redisOptTokenStore
)
{
this
.
redisOptTokenStore
=
redisOptTokenStore
;
...
...
maxkey-core/src/main/java/org/maxkey/entity/ChangePassword.java
浏览文件 @
7ddde380
...
...
@@ -67,6 +67,11 @@ public class ChangePassword extends JpaBaseEntity{
this
.
setInstId
(
userInfo
.
getInstId
());
}
public
void
clearPassword
()
{
this
.
password
=
""
;
this
.
decipherable
=
""
;
}
/**
* @return the id
*/
...
...
maxkey-core/src/main/java/org/maxkey/persistence/repository/PasswordPolicyRepository.java
浏览文件 @
7ddde380
...
...
@@ -152,6 +152,7 @@ public class PasswordPolicyRepository {
public
ArrayList
<
Rule
>
getPasswordPolicyRuleList
()
{
getPasswordPolicy
();
return
passwordPolicyRuleList
;
}
...
...
maxkey-web-frontend/maxkey-web-app/src/app/app.module.ts
浏览文件 @
7ddde380
...
...
@@ -106,4 +106,4 @@ import { Observable } from 'rxjs';
providers
:
[...
LANG_PROVIDES
,
...
INTERCEPTOR_PROVIDES
,
...
I18NSERVICE_PROVIDES
,
...
APPINIT_PROVIDES
],
bootstrap
:
[
AppComponent
]
})
export
class
AppModule
{}
export
class
AppModule
{
}
maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/forgot/forgot.component.html
0 → 100644
浏览文件 @
7ddde380
<h3>
{{ 'mxk.forgot.forgot' | i18n }}
</h3>
<form
nz-form
[formGroup]=
"formGroup"
role=
"form"
>
<nz-form-item
style=
"width: 100%"
>
<nz-steps
nzType=
"navigation"
[nzCurrent]=
"step"
style=
"width: 100%"
>
<nz-step
nzTitle=
"{{ 'mxk.forgot.step1' | i18n }}"
nzDescription=
""
>
</nz-step>
<nz-step
nzTitle=
"{{ 'mxk.forgot.step2' | i18n }}"
nzDescription=
""
></nz-step>
</nz-steps>
</nz-form-item>
<nz-form-item
style=
"width: 100%"
*ngIf=
"step === 0"
>
<nz-form-item
style=
"width: 100%"
>
<nz-radio-group
[(ngModel)]=
"forgotType"
[ngModelOptions]=
"{ standalone: true }"
style=
"margin-bottom: 8px; width: 100%"
nzSize=
"large"
nzButtonStyle=
"solid"
(ngModelChange)=
"ngModelChange()"
>
<label
nz-radio-button
[nzValue]=
"'mobile'"
style=
"width: 50%"
>
{{ 'mxk.forgot.type.mobile' | i18n }}
</label>
<label
nz-radio-button
[nzValue]=
"'email'"
style=
"width: 50%"
>
{{ 'mxk.forgot.type.email' | i18n }}
</label>
</nz-radio-group>
</nz-form-item>
<nz-form-item
style=
"width: 100%"
*ngIf=
"forgotType === 'email'"
>
<nz-form-control
nzErrorTip=
""
>
<nz-input-group
nzSize=
"large"
nzPrefixIcon=
"mail"
>
<input
nz-input
formControlName=
"email"
placeholder=
"{{ 'mxk.forgot.email' | i18n }}"
/>
</nz-input-group>
</nz-form-control>
</nz-form-item>
<nz-form-item
style=
"width: 100%"
*ngIf=
"forgotType === 'mobile'"
>
<nz-form-control
[nzErrorTip]=
""
>
<nz-input-group
nzSize=
"large"
nzPrefixIcon=
"mobile"
>
<input
nz-input
formControlName=
"mobile"
placeholder=
"{{ 'mxk.forgot.mobile' | i18n }}"
/>
</nz-input-group>
<ng-template
#mobileErrorTip
let-i
>
<ng-container
*ngIf=
"i.errors.required"
>
{{ 'validation.phone-number.required' | i18n }}
</ng-container>
<ng-container
*ngIf=
"i.errors.pattern"
>
{{ 'validation.phone-number.wrong-format' | i18n }}
</ng-container>
</ng-template>
</nz-form-control>
</nz-form-item>
<nz-form-item
style=
"width: 100%"
>
<nz-form-control
nzErrorTip=
""
>
<nz-input-group
nzSearch
nzSize=
"large"
nzPrefixIcon=
"lock"
nzSearch
[nzAddOnAfter]=
"suffixImageCaptchaButton"
>
<input
type=
"text"
formControlName=
"captcha"
nz-input
placeholder=
"{{ 'mxk.forgot.captcha' | i18n }}"
/>
</nz-input-group>
<ng-template
#suffixImageCaptchaButton
>
<img
src=
"{{ imageCaptcha }}"
(click)=
"getImageCaptcha()"
/>
</ng-template>
</nz-form-control>
</nz-form-item>
<nz-form-item
style=
"width: 100%"
>
<nz-form-control
[nzErrorTip]=
"'' | i18n"
>
<nz-input-group
nzSize=
"large"
nzPrefixIcon=
"mail"
nzSearch
[nzAddOnAfter]=
"suffixSendOtpCodeButton"
>
<input
nz-input
formControlName=
"otpCaptcha"
placeholder=
"{{ 'mxk.login.text.captcha' | i18n }}"
/>
</nz-input-group>
<ng-template
#suffixSendOtpCodeButton
>
<button
type=
"button"
nz-button
nzSize=
"large"
(click)=
"sendOtpCode()"
[disabled]=
"count > 0"
nzBlock
[nzLoading]=
"loading"
>
{{ count ? count + 's' : ('mxk.forgot.sendCaptcha' | i18n) }}
</button>
</ng-template>
</nz-form-control>
</nz-form-item>
<nz-form-item
style=
"width: 100%"
>
<button
nz-button
nzType=
"primary"
nzSize=
"large"
class=
"submit"
(click)=
"onNextReset($event)"
>
{{ 'mxk.forgot.next' | i18n }}
</button>
<a
class=
"login"
routerLink=
"/passport/login"
>
{{ 'mxk.forgot.login' | i18n }}
</a>
</nz-form-item>
</nz-form-item>
<nz-form-item
style=
"width: 100%"
*ngIf=
"step === 1"
>
<nz-form-item
style=
"width: 100%"
>
<nz-form-label
nzRequired
nzFor=
"password"
>
{{ 'mxk.password.password' | i18n }}
</nz-form-label>
</nz-form-item>
<nz-form-item
style=
"width: 100%"
>
<nz-form-control
nzErrorTip=
"The input is not valid password!"
>
<nz-input-group
nzSize=
"large"
[nzSuffix]=
"suffixPasswordTemplate"
style=
"width: 100%"
>
<input
[type]=
"passwordVisible ? 'text' : 'password'"
nz-input
placeholder=
"new password"
[(ngModel)]=
"form.model.password"
formControlName=
"password"
id=
"password"
/>
</nz-input-group>
<ng-template
#suffixPasswordTemplate
>
<i
nz-icon
[nzType]=
"passwordVisible ? 'eye-invisible' : 'eye'"
(click)=
"passwordVisible = !passwordVisible"
></i>
</ng-template>
</nz-form-control>
</nz-form-item>
<nz-form-item
style=
"width: 100%"
>
<nz-form-label
nzRequired
nzFor=
"confirmPassword"
>
{{ 'mxk.password.confirmPassword' | i18n }}
</nz-form-label>
</nz-form-item>
<nz-form-item
style=
"width: 100%"
>
<nz-form-control
nzErrorTip=
"The input is not valid confirmPassword!"
>
<input
nz-input
type=
"password"
nzSize=
"large"
placeholder=
"confirm password"
[(ngModel)]=
"form.model.confirmPassword"
formControlName=
"confirmPassword"
name=
"confirmPassword"
id=
"confirmPassword"
/>
</nz-form-control>
</nz-form-item>
<nz-form-item
style=
"width: 100%"
>
<button
nz-button
nzType=
"primary"
nzSize=
"large"
class=
"submit"
(click)=
"onSubmit($event)"
>
{{ 'mxk.forgot.submit' | i18n }}
</button>
<a
class=
"login"
routerLink=
"/passport/login"
>
{{ 'mxk.forgot.login' | i18n }}
</a>
</nz-form-item>
</nz-form-item>
</form>
maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/forgot/forgot.component.less
0 → 100644
浏览文件 @
7ddde380
@import '@delon/theme/index';
:host {
display: block;
width: 460px;
margin: 0 auto;
::ng-deep {
.ant-tabs .ant-tabs-bar {
margin-bottom: 24px;
text-align: center;
border-bottom: 0;
}
}
.login {
float: right;
line-height: @btn-height-lg;
}
}
\ No newline at end of file
maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/forgot/forgot.component.spec.ts
0 → 100644
浏览文件 @
7ddde380
import
{
ComponentFixture
,
TestBed
}
from
'
@angular/core/testing
'
;
import
{
ForgotComponent
}
from
'
./forgot.component
'
;
describe
(
'
ForgotComponent
'
,
()
=>
{
let
component
:
ForgotComponent
;
let
fixture
:
ComponentFixture
<
ForgotComponent
>
;
beforeEach
(
async
()
=>
{
await
TestBed
.
configureTestingModule
({
declarations
:
[
ForgotComponent
]
})
.
compileComponents
();
});
beforeEach
(()
=>
{
fixture
=
TestBed
.
createComponent
(
ForgotComponent
);
component
=
fixture
.
componentInstance
;
fixture
.
detectChanges
();
});
it
(
'
should create
'
,
()
=>
{
expect
(
component
).
toBeTruthy
();
});
});
maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/forgot/forgot.component.ts
0 → 100644
浏览文件 @
7ddde380
import
{
Component
,
OnInit
,
ChangeDetectorRef
}
from
'
@angular/core
'
;
import
{
AbstractControl
,
FormBuilder
,
FormGroup
,
Validators
}
from
'
@angular/forms
'
;
import
{
Router
,
ActivatedRoute
}
from
'
@angular/router
'
;
import
{
NzMessageService
}
from
'
ng-zorro-antd/message
'
;
import
{
NzStepsModule
}
from
'
ng-zorro-antd/steps
'
;
import
{
ChangePassword
}
from
'
../../../entity/ChangePassword
'
;
import
{
ForgotPasswordService
}
from
'
../../../service/forgot-password.service
'
;
import
{
ImageCaptchaService
}
from
'
../../../service/image-captcha.service
'
;
import
{
PasswordService
}
from
'
../../../service/password.service
'
;
@
Component
({
selector
:
'
app-forgot
'
,
templateUrl
:
'
./forgot.component.html
'
,
styleUrls
:
[
'
./forgot.component.less
'
]
})
export
class
ForgotComponent
implements
OnInit
{
form
:
{
submitting
:
boolean
;
model
:
ChangePassword
;
}
=
{
submitting
:
false
,
model
:
new
ChangePassword
()
};
imageCaptcha
=
''
;
formGroup
:
FormGroup
;
state
=
''
;
step
=
0
;
forgotType
=
'
mobile
'
;
passwordVisible
=
false
;
loading
=
false
;
count
=
0
;
interval$
:
any
;
userId
=
''
;
username
=
''
;
constructor
(
fb
:
FormBuilder
,
private
forgotPasswordService
:
ForgotPasswordService
,
private
imageCaptchaService
:
ImageCaptchaService
,
private
msg
:
NzMessageService
,
private
cdr
:
ChangeDetectorRef
)
{
this
.
formGroup
=
fb
.
group
({
mobile
:
[
null
,
[
Validators
.
required
,
Validators
.
pattern
(
/^1
\d{10}
$/
)]],
email
:
[
null
,
[
Validators
.
required
]],
password
:
[
null
,
[
Validators
.
required
]],
captcha
:
[
null
,
[
Validators
.
required
]],
otpCaptcha
:
[
null
,
[
Validators
.
required
]],
confirmPassword
:
[
null
,
[
Validators
.
required
]]
});
}
get
email
():
AbstractControl
{
return
this
.
formGroup
.
get
(
'
email
'
)
!
;
}
get
password
():
AbstractControl
{
return
this
.
formGroup
.
get
(
'
password
'
)
!
;
}
get
confirmPassword
():
AbstractControl
{
return
this
.
formGroup
.
get
(
'
confirmPassword
'
)
!
;
}
get
mobile
():
AbstractControl
{
return
this
.
formGroup
.
get
(
'
mobile
'
)
!
;
}
get
captcha
():
AbstractControl
{
return
this
.
formGroup
.
get
(
'
captcha
'
)
!
;
}
get
otpCaptcha
():
AbstractControl
{
return
this
.
formGroup
.
get
(
'
otpCaptcha
'
)
!
;
}
ngOnInit
():
void
{
this
.
getImageCaptcha
();
}
getImageCaptcha
():
void
{
this
.
imageCaptchaService
.
captcha
({}).
subscribe
(
res
=>
{
this
.
imageCaptcha
=
res
.
data
.
image
;
this
.
state
=
res
.
data
.
state
;
this
.
cdr
.
detectChanges
();
});
}
//send sms
sendOtpCode
():
void
{
if
(
this
.
forgotType
==
'
mobile
'
&&
this
.
mobile
.
invalid
)
{
this
.
mobile
.
markAsDirty
({
onlySelf
:
true
});
this
.
mobile
.
updateValueAndValidity
({
onlySelf
:
true
});
return
;
}
if
(
this
.
forgotType
==
'
email
'
&&
this
.
email
.
invalid
)
{
this
.
email
.
markAsDirty
({
onlySelf
:
true
});
this
.
email
.
updateValueAndValidity
({
onlySelf
:
true
});
return
;
}
if
(
this
.
forgotType
==
'
mobile
'
)
{
this
.
forgotPasswordService
.
produceOtp
({
mobile
:
this
.
mobile
.
value
,
state
:
this
.
state
,
captcha
:
this
.
captcha
.
value
})
.
subscribe
(
res
=>
{
if
(
res
.
code
!==
0
)
{
this
.
msg
.
success
(
`发送失败`
);
this
.
getImageCaptcha
();
this
.
cdr
.
detectChanges
();
}
this
.
userId
=
res
.
data
.
userId
;
this
.
username
=
res
.
data
.
username
;
//console.log(res.data);
});
}
else
if
(
this
.
forgotType
==
'
email
'
)
{
this
.
forgotPasswordService
.
produceEmailOtp
({
email
:
this
.
email
.
value
,
state
:
this
.
state
,
captcha
:
this
.
captcha
.
value
})
.
subscribe
(
res
=>
{
if
(
res
.
code
!==
0
)
{
this
.
msg
.
success
(
`发送失败`
);
this
.
getImageCaptcha
();
this
.
cdr
.
detectChanges
();
}
this
.
userId
=
res
.
data
.
userId
;
this
.
username
=
res
.
data
.
username
;
//console.log(res.data);
});
}
this
.
count
=
59
;
this
.
interval$
=
setInterval
(()
=>
{
this
.
count
-=
1
;
if
(
this
.
count
<=
0
)
{
clearInterval
(
this
.
interval$
);
}
this
.
cdr
.
detectChanges
();
},
1000
);
}
onNextReset
(
e
:
MouseEvent
)
{
if
(
this
.
otpCaptcha
.
invalid
)
{
this
.
otpCaptcha
.
markAsDirty
({
onlySelf
:
true
});
this
.
otpCaptcha
.
updateValueAndValidity
({
onlySelf
:
true
});
return
;
}
this
.
step
=
1
;
}
onSubmit
(
e
:
MouseEvent
)
{
this
.
forgotPasswordService
.
setPassWord
({
forgotType
:
this
.
forgotType
,
userId
:
this
.
userId
,
username
:
this
.
username
,
password
:
this
.
password
.
value
,
confirmPassword
:
this
.
confirmPassword
.
value
,
otpCaptcha
:
this
.
otpCaptcha
.
value
,
state
:
this
.
state
})
.
subscribe
(
res
=>
{
if
(
res
.
code
!==
0
)
{
this
.
msg
.
success
(
`密码修改失败`
);
this
.
getImageCaptcha
();
this
.
step
=
0
;
this
.
cdr
.
detectChanges
();
}
this
.
msg
.
success
(
`密码修改成功`
);
});
}
ngModelChange
()
{
if
(
this
.
forgotType
==
'
email
'
)
{
this
.
mobile
.
reset
();
}
if
(
this
.
forgotType
==
'
mobile
'
)
{
this
.
email
.
reset
();
}
}
}
maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/login/login.component.html
浏览文件 @
7ddde380
...
...
@@ -89,7 +89,7 @@
<label
nz-checkbox
formControlName=
"remember"
>
{{ 'mxk.login.remember-me' | i18n }}
</label>
</nz-col>
<nz-col
[nzSpan]=
"12"
class=
"text-right"
>
<a
class=
"forgot"
routerLink=
"/passport/
register
"
>
{{ 'mxk.login.forgot-password' | i18n }}
</a></nz-col
<a
class=
"forgot"
routerLink=
"/passport/
forgot
"
>
{{ 'mxk.login.forgot-password' | i18n }}
</a></nz-col
>
</nz-form-item>
<nz-form-item
*ngIf=
"loginType == 'normal' || loginType == 'mobile'"
>
...
...
maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/passport-routing.module.ts
浏览文件 @
7ddde380
...
...
@@ -3,6 +3,7 @@ import { RouterModule, Routes } from '@angular/router';
import
{
LayoutPassportComponent
}
from
'
../../layout/passport/passport.component
'
;
import
{
CallbackComponent
}
from
'
./callback.component
'
;
import
{
ForgotComponent
}
from
'
./forgot/forgot.component
'
;
import
{
UserLockComponent
}
from
'
./lock/lock.component
'
;
import
{
UserLoginComponent
}
from
'
./login/login.component
'
;
import
{
UserRegisterResultComponent
}
from
'
./register-result/register-result.component
'
;
...
...
@@ -29,6 +30,11 @@ const routes: Routes = [
component
:
UserRegisterResultComponent
,
data
:
{
title
:
'
注册结果
'
,
titleI18n
:
'
app.register.register
'
}
},
{
path
:
'
forgot
'
,
component
:
ForgotComponent
,
data
:
{
title
:
'
忘记密码
'
,
titleI18n
:
'
app.forgot.forgot
'
}
},
{
path
:
'
lock
'
,
component
:
UserLockComponent
,
...
...
maxkey-web-frontend/maxkey-web-app/src/app/routes/passport/passport.module.ts
浏览文件 @
7ddde380
import
{
NgModule
}
from
'
@angular/core
'
;
import
{
SharedModule
}
from
'
@shared
'
;
import
{
NzStepsModule
}
from
'
ng-zorro-antd/steps
'
;
import
{
CallbackComponent
}
from
'
./callback.component
'
;
import
{
ForgotComponent
}
from
'
./forgot/forgot.component
'
;
import
{
UserLockComponent
}
from
'
./lock/lock.component
'
;
import
{
UserLoginComponent
}
from
'
./login/login.component
'
;
import
{
PassportRoutingModule
}
from
'
./passport-routing.module
'
;
...
...
@@ -11,7 +13,7 @@ import { UserRegisterComponent } from './register/register.component';
const
COMPONENTS
=
[
UserLoginComponent
,
UserRegisterResultComponent
,
UserRegisterComponent
,
UserLockComponent
,
CallbackComponent
];
@
NgModule
({
imports
:
[
SharedModule
,
PassportRoutingModule
],
declarations
:
[...
COMPONENTS
]
imports
:
[
SharedModule
,
PassportRoutingModule
,
NzStepsModule
],
declarations
:
[...
COMPONENTS
,
ForgotComponent
]
})
export
class
PassportModule
{}
export
class
PassportModule
{
}
maxkey-web-frontend/maxkey-web-app/src/app/service/forgot-password.service.ts
0 → 100644
浏览文件 @
7ddde380
import
{
Injectable
,
Inject
}
from
'
@angular/core
'
;
import
{
_HttpClient
,
User
}
from
'
@delon/theme
'
;
@
Injectable
({
providedIn
:
'
root
'
})
export
class
ForgotPasswordService
{
constructor
(
private
http
:
_HttpClient
)
{
}
produceOtp
(
param
:
any
)
{
return
this
.
http
.
get
(
'
/forgotpassword/produceOtp?_allow_anonymous=true
'
,
param
);
}
produceEmailOtp
(
param
:
any
)
{
return
this
.
http
.
get
(
`/forgotpassword/produceEmailOtp?_allow_anonymous=true`
,
param
);
}
setPassWord
(
param
:
any
)
{
return
this
.
http
.
get
(
'
/forgotpassword/setpassword?_allow_anonymous=true
'
,
param
);
}
}
maxkey-web-frontend/maxkey-web-app/src/assets/i18n/en-US.json
浏览文件 @
7ddde380
...
...
@@ -21,6 +21,22 @@
"text.captcha"
:
"Captcha"
,
"text.smscode"
:
"Code"
},
"forgot"
:{
"forgot"
:
"Forgot Password"
,
"step1"
:
"Authentication"
,
"step2"
:
"Resetting Password"
,
"type.mobile"
:
"By Mobile"
,
"type.email"
:
"By Email"
,
"mobile"
:
"Mobile Phone Number"
,
"email"
:
"Email"
,
"captcha"
:
"Picture Captcha"
,
"sendCaptcha"
:
"Send Captcha"
,
"password"
:
"New Password"
,
"confirmPassword"
:
"Confirm Password"
,
"login"
:
"Back Login"
,
"next"
:
"Next"
,
"submit"
:
"Confirm"
},
"menu"
:
{
"applist"
:
"Apps"
,
"sessions"
:
"Sessions"
,
...
...
@@ -807,6 +823,7 @@
"app.login.text.password"
:
"Password"
,
"app.login.text.captcha"
:
"CAPTCHA"
,
"app.login.text.smscode"
:
"Code"
,
"app.forgot.forgot"
:
"Forgot Password"
,
"app.register.register"
:
"Register"
,
"app.register.get-verification-code"
:
"Get code"
,
"app.register.sign-in"
:
"Already have an account?"
,
...
...
maxkey-web-frontend/maxkey-web-app/src/assets/i18n/zh-CN.json
浏览文件 @
7ddde380
...
...
@@ -16,11 +16,27 @@
"signup"
:
"用户注册"
,
"login"
:
"登录"
,
"text.username"
:
"用户名"
,
"text.mobile"
:
"手机号"
,
"text.mobile"
:
"手机号
码
"
,
"text.password"
:
"密码"
,
"text.captcha"
:
"验证码"
,
"text.smscode"
:
"验证码"
},
"forgot"
:{
"forgot"
:
"忘记密码"
,
"step1"
:
"验证身份"
,
"step2"
:
"设置新密码"
,
"type.mobile"
:
"手机找回"
,
"type.email"
:
"邮箱找回"
,
"mobile"
:
"手机号码"
,
"email"
:
"邮箱"
,
"captcha"
:
"图形验证码"
,
"sendCaptcha"
:
"发送验证码"
,
"password"
:
"新密码"
,
"confirmPassword"
:
"确认新密码"
,
"login"
:
"返回登录"
,
"next"
:
"下一步"
,
"submit"
:
"提交"
},
"menu"
:
{
"applist"
:
"应用"
,
"sessions"
:
"会话"
,
...
...
@@ -805,6 +821,7 @@
"app.login.text.password"
:
"密码"
,
"app.login.text.captcha"
:
"验证码"
,
"app.login.text.smscode"
:
"验证码"
,
"app.forgot.forgot"
:
"忘记密码"
,
"app.register.register"
:
"注册"
,
"app.register.get-verification-code"
:
"获取验证码"
,
"app.register.sign-in"
:
"使用已有账户登录"
,
...
...
maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/contorller/ChangePasswodController.java
浏览文件 @
7ddde380
/*
* Copyright [202
0
] [MaxKey of copyright http://www.maxkey.top]
* Copyright [202
2
] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
...
...
@@ -17,31 +17,21 @@
package
org.maxkey.web.contorller
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
org.maxkey.authn.annotation.CurrentUser
;
import
org.maxkey.constants.ConstsOperateMessage
;
import
org.maxkey.constants.ConstsPasswordSetType
;
import
org.maxkey.constants.ConstsTimeInterval
;
import
org.maxkey.entity.ChangePassword
;
import
org.maxkey.entity.Message
;
import
org.maxkey.entity.UserInfo
;
import
org.maxkey.persistence.repository.PasswordPolicyValidator
;
import
org.maxkey.persistence.service.UserInfoService
;
import
org.maxkey.web.WebConstants
;
import
org.maxkey.web.WebContext
;
import
org.maxkey.web.message.Message
;
import
org.maxkey.web.message.MessageType
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.MediaType
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.stereotype.Controller
;
import
org.springframework.web.bind.annotation.ModelAttribute
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
org.springframework.web.bind.annotation.ResponseBody
;
import
org.springframework.web.servlet.ModelAndView
;
@Controller
@RequestMapping
(
value
={
"/config"
})
...
...
@@ -52,8 +42,8 @@ public class ChangePasswodController {
private
UserInfoService
userInfoService
;
@ResponseBody
@RequestMapping
(
value
=
"/changePassword"
)
public
Message
changePasswod
(
@RequestMapping
(
value
=
{
"/changePassword"
},
produces
=
{
MediaType
.
APPLICATION_JSON_VALUE
})
public
ResponseEntity
<?>
changePasswod
(
@RequestBody
ChangePassword
changePassword
,
@CurrentUser
UserInfo
currentUser
)
{
...
...
@@ -62,12 +52,9 @@ public class ChangePasswodController {
changePassword
.
setInstId
(
currentUser
.
getInstId
());
changePassword
.
setPasswordSetType
(
ConstsPasswordSetType
.
PASSWORD_NORMAL
);
if
(
userInfoService
.
changePassword
(
changePassword
))
{
return
new
Message
(
WebContext
.
getI18nValue
(
ConstsOperateMessage
.
UPDATE_SUCCESS
),
MessageType
.
success
);
return
new
Message
<
ChangePassword
>().
buildResponse
(
);
}
else
{
return
new
Message
(
WebContext
.
getI18nValue
(
ConstsOperateMessage
.
UPDATE_ERROR
)+
"<br>"
+
WebContext
.
getAttribute
(
PasswordPolicyValidator
.
PASSWORD_POLICY_VALIDATE_RESULT
),
MessageType
.
error
);
return
new
Message
<
ChangePassword
>(
Message
.
ERROR
).
buildResponse
();
}
}
...
...
maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/contorller/ForgotPasswordContorller.java
浏览文件 @
7ddde380
/*
* Copyright [202
0
] [MaxKey of copyright http://www.maxkey.top]
* Copyright [202
2
] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
...
...
@@ -19,22 +19,26 @@ package org.maxkey.web.contorller;
import
java.util.regex.Pattern
;
import
org.apache.commons.lang3.StringUtils
;
import
org.maxkey.authn.jwt.AuthJwtService
;
import
org.maxkey.configuration.EmailConfig
;
import
org.maxkey.entity.ChangePassword
;
import
org.maxkey.entity.Message
;
import
org.maxkey.entity.UserInfo
;
import
org.maxkey.password.onetimepwd.AbstractOtpAuthn
;
import
org.maxkey.password.onetimepwd.OtpAuthnService
;
import
org.maxkey.persistence.repository.PasswordPolicyValidator
;
import
org.maxkey.persistence.service.UserInfoService
;
import
org.maxkey.web.WebConstants
;
import
org.maxkey.web.WebContext
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Qualifier
;
import
org.springframework.http.MediaType
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.stereotype.Controller
;
import
org.springframework.web.bind.annotation.ModelAttribute
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
org.springframework.web.
servlet.ModelAndView
;
import
org.springframework.web.
bind.annotation.ResponseBody
;
@Controller
@RequestMapping
(
value
=
{
"/forgotpassword"
})
...
...
@@ -45,7 +49,7 @@ public class ForgotPasswordContorller {
"^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$"
);
Pattern
mobileRegex
=
Pattern
.
compile
(
"^
(13[4,5,6,7,8,9]|15[0,8,9,1,7]|188|187)\\\\d{8
}$"
);
"^
[1][3,4,5,7,8][0-9]{9
}$"
);
@Autowired
EmailConfig
emailConfig
;
...
...
@@ -64,101 +68,107 @@ public class ForgotPasswordContorller {
}
@Autowired
private
UserInfoService
userInfo
Service
;
AuthJwtService
authJwt
Service
;
@Autowired
@Qualifier
(
"mailOtpAuthn"
)
protected
AbstractOtpAuthn
mailOtpAuthn
;
UserInfoService
userInfoService
;
@Autowired
@Qualifier
(
"otpAuthnService"
)
OtpAuthnService
otpAuthnService
;
@RequestMapping
(
value
=
{
"/forward"
})
public
ModelAndView
forwardreg
()
{
_logger
.
debug
(
"forgotpassword /forgotpassword/forward."
);
return
new
ModelAndView
(
"forgotpassword/findpwd"
);
}
@RequestMapping
(
value
=
{
"/emailmobile"
})
public
ModelAndView
email
(
@RequestParam
String
emailMobile
,
@RequestParam
String
captcha
)
{
_logger
.
debug
(
"forgotpassword /forgotpassword/emailmobile."
);
_logger
.
debug
(
"emailMobile : "
+
emailMobile
);
int
forgotType
=
ForgotType
.
NOTFOUND
;
UserInfo
userInfo
=
null
;
if
(
captcha
!=
null
&&
captcha
.
equals
(
WebContext
.
getSession
().
getAttribute
(
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
.
findByEmailMobile
(
emailMobile
);
if
(
null
!=
userInfo
)
{
if
(
forgotType
==
ForgotType
.
EMAIL
)
{
mailOtpAuthn
.
produce
(
userInfo
);
}
else
if
(
forgotType
==
ForgotType
.
MOBILE
)
{
AbstractOtpAuthn
smsOtpAuthn
=
otpAuthnService
.
getByInstId
(
userInfo
.
getInstId
());
smsOtpAuthn
.
produce
(
userInfo
);
}
}
}
else
{
_logger
.
debug
(
"login captcha valid error."
);
forgotType
=
ForgotType
.
CAPTCHAERROR
;
@ResponseBody
@RequestMapping
(
value
=
{
"/produceOtp"
},
produces
=
{
MediaType
.
APPLICATION_JSON_VALUE
})
public
ResponseEntity
<?>
produceOtp
(
@RequestParam
String
mobile
,
@RequestParam
String
state
,
@RequestParam
String
captcha
)
{
_logger
.
debug
(
"forgotpassword /forgotpassword/produceOtp."
);
_logger
.
debug
(
" Mobile {}: "
,
mobile
);
if
(!
authJwtService
.
validateCaptcha
(
state
,
captcha
))
{
_logger
.
debug
(
"login captcha valid error."
);
return
new
Message
<
ChangePassword
>(
Message
.
FAIL
).
buildResponse
();
}
ModelAndView
modelAndView
=
new
ModelAndView
(
"forgotpassword/resetpwd"
);
modelAndView
.
addObject
(
"userId"
,
userInfo
==
null
?
""
:
userInfo
.
getId
());
modelAndView
.
addObject
(
"username"
,
userInfo
==
null
?
""
:
userInfo
.
getUsername
());
modelAndView
.
addObject
(
"emailMobile"
,
emailMobile
);
modelAndView
.
addObject
(
"forgotType"
,
forgotType
);
ChangePassword
change
=
null
;
_logger
.
debug
(
"Mobile Regex matches {}"
,
mobileRegex
.
matcher
(
mobile
).
matches
());
if
(
StringUtils
.
isNotBlank
(
mobile
)
&&
mobileRegex
.
matcher
(
mobile
).
matches
())
{
UserInfo
userInfo
=
userInfoService
.
findByEmailMobile
(
mobile
);
if
(
userInfo
!=
null
)
{
change
=
new
ChangePassword
(
userInfo
);
change
.
clearPassword
();
AbstractOtpAuthn
smsOtpAuthn
=
otpAuthnService
.
getByInstId
(
userInfo
.
getInstId
());
smsOtpAuthn
.
produce
(
userInfo
);
return
new
Message
<
ChangePassword
>(
change
).
buildResponse
();
}
}
return
new
Message
<
ChangePassword
>(
Message
.
FAIL
).
buildResponse
();
}
@ResponseBody
@RequestMapping
(
value
=
{
"/produceEmailOtp"
},
produces
=
{
MediaType
.
APPLICATION_JSON_VALUE
})
public
ResponseEntity
<?>
produceEmailOtp
(
@RequestParam
String
email
,
@RequestParam
String
state
,
@RequestParam
String
captcha
)
{
_logger
.
debug
(
"forgotpassword /forgotpassword/produceEmailOtp."
);
_logger
.
debug
(
"Email {} : "
,
email
);
if
(!
authJwtService
.
validateCaptcha
(
state
,
captcha
))
{
_logger
.
debug
(
"login captcha valid error."
);
return
new
Message
<
ChangePassword
>(
Message
.
FAIL
).
buildResponse
();
}
return
modelAndView
;
ChangePassword
change
=
null
;
if
(
StringUtils
.
isNotBlank
(
email
)
&&
emailRegex
.
matcher
(
email
).
matches
())
{
UserInfo
userInfo
=
userInfoService
.
findByEmailMobile
(
email
);
if
(
userInfo
!=
null
)
{
change
=
new
ChangePassword
(
userInfo
);
change
.
clearPassword
();
AbstractOtpAuthn
mailOtpAuthn
=
otpAuthnService
.
getMailOtpAuthn
(
userInfo
.
getInstId
());
mailOtpAuthn
.
produce
(
userInfo
);
return
new
Message
<
ChangePassword
>(
change
).
buildResponse
();
}
}
return
new
Message
<
ChangePassword
>(
Message
.
FAIL
).
buildResponse
();
}
@RequestMapping
(
value
=
{
"/setpassword"
})
public
ModelAndView
setPassWord
(
@RequestParam
String
userId
,
@RequestParam
String
username
,
@RequestParam
int
forgotType
,
@RequestParam
String
password
,
@RequestParam
String
confirmpassword
,
@RequestParam
String
captcha
)
{
_logger
.
debug
(
"forgotPassword /forgotpassword/pwdreseted."
);
ModelAndView
modelAndView
=
new
ModelAndView
(
"forgotpassword/pwdreseted"
);
if
(
null
!=
password
&&
password
.
equals
(
confirmpassword
))
{
UserInfo
userInfo
=
new
UserInfo
();
userInfo
.
setId
(
userId
);
userInfo
.
setUsername
(
username
);
userInfo
.
setPassword
(
password
);
userInfo
.
setDecipherable
(
password
);
UserInfo
loadedUserInfo
=
userInfoService
.
findByUsername
(
username
);
AbstractOtpAuthn
smsOtpAuthn
=
otpAuthnService
.
getByInstId
(
loadedUserInfo
.
getInstId
());
if
((
forgotType
==
ForgotType
.
EMAIL
&&
mailOtpAuthn
.
validate
(
userInfo
,
captcha
))
||
(
forgotType
==
ForgotType
.
MOBILE
&&
smsOtpAuthn
.
validate
(
userInfo
,
captcha
))
)
{
/**
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
);
}
}
else
{
modelAndView
.
addObject
(
"passwordResetResult"
,
PasswordResetResult
.
PASSWORDERROR
);
public
ResponseEntity
<?>
setPassWord
(
@ModelAttribute
ChangePassword
changePassword
,
@RequestParam
String
forgotType
,
@RequestParam
String
otpCaptcha
,
@RequestParam
String
state
)
{
_logger
.
debug
(
"forgotPassword /forgotpassword/setpassword."
);
if
(
StringUtils
.
isNotBlank
(
changePassword
.
getPassword
()
)
&&
changePassword
.
getPassword
().
equals
(
changePassword
.
getConfirmPassword
()))
{
UserInfo
loadedUserInfo
=
userInfoService
.
get
(
changePassword
.
getUserId
());
if
(
loadedUserInfo
!=
null
)
{
AbstractOtpAuthn
smsOtpAuthn
=
otpAuthnService
.
getByInstId
(
loadedUserInfo
.
getInstId
());
AbstractOtpAuthn
mailOtpAuthn
=
otpAuthnService
.
getMailOtpAuthn
(
loadedUserInfo
.
getInstId
());
if
(
(
forgotType
.
equalsIgnoreCase
(
"email"
)
&&
mailOtpAuthn
!=
null
&&
mailOtpAuthn
.
validate
(
loadedUserInfo
,
otpCaptcha
))
||
(
forgotType
.
equalsIgnoreCase
(
"mobile"
)
&&
smsOtpAuthn
!=
null
&&
smsOtpAuthn
.
validate
(
loadedUserInfo
,
otpCaptcha
))
)
{
if
(
userInfoService
.
changePassword
(
changePassword
,
true
))
{
return
new
Message
<
ChangePassword
>(
Message
.
SUCCESS
).
buildResponse
();
}
else
{
return
new
Message
<
ChangePassword
>(
Message
.
FAIL
).
buildResponse
();
}
}
else
{
return
new
Message
<
ChangePassword
>(
Message
.
FAIL
).
buildResponse
();
}
}
}
return
modelAndView
;
return
new
Message
<
ChangePassword
>(
Message
.
FAIL
).
buildResponse
()
;
}
}
maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/contorller/SafeController.java
浏览文件 @
7ddde380
...
...
@@ -46,9 +46,6 @@ public class SafeController {
@Autowired
private
UserInfoService
userInfoService
;
@RequestMapping
(
value
=
"/forward/setting"
)
public
ModelAndView
fowardSetting
(
@CurrentUser
UserInfo
currentUser
)
{
ModelAndView
modelAndView
=
new
ModelAndView
(
"safe/setting"
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录