Browse Source

PasswordPolicy

Crystal.Sea 5 years ago
parent
commit
6058096896

+ 5 - 3
ReleaseNotes.txt

@@ -1,12 +1,14 @@
 MaxKey v 2.2.0 GA	2020/**/**
-	*(MAXKEY-200801)   官方网站内容调整,初步增加英文版支持
-	*(MAXKEY-200802)  密码策略优化
-	*(MAXKEY-200803) CAS协议增加自定义参数回传
+	*(MAXKEY-200801)  官方网站内容调整,初步增加英文版支持,增加新闻、合作伙伴及与CAS等开源产品对比
+	*(MAXKEY-200802)  使用Passay增强密码策略,分离出静态密码策略和动态密码策略
+	*(MAXKEY-200803)  CAS协议增加自定义参数回传
 	*(MAXKEY-200804)  优化开发集成指南
 	*(MAXKEY-200805)  删除冗余的文件和文件夹
 	*(MAXKEY-200806)  CAS适配器支持
 	*(MAXKEY-200807)  Maven版本支持
 	*(MAXKEY-200808)  CAS spring boot demo
+	*(MAXKEY-200809)  MGT管理访问找不到页面修复
+	*(MAXKEY-200810)  MGT管理密码修改增加自动密码生成
 	
 	
 	

+ 4 - 0
maxkey-core/src/main/java/org/maxkey/crypto/password/PasswordGen.java

@@ -39,6 +39,10 @@ public class PasswordGen {
     public PasswordGen() {
         length = DEFAULT_LENGTH;
     }
+    
+    public PasswordGen(int length) {
+        this.length = length;
+    }
 
     public String gen() {
         this.length = DEFAULT_LENGTH;

+ 72 - 20
maxkey-core/src/main/java/org/maxkey/domain/PasswordPolicy.java

@@ -104,7 +104,23 @@ public class PasswordPolicy extends JpaBaseDomain implements java.io.Serializabl
      * not include password list
      */
     @Column
-    private String simplePasswords;
+    private int history;
+    
+    @Column
+    private int dictionary;
+    
+    @Column
+    private int alphabetical;
+    
+    @Column
+    private int numerical;
+    
+    @Column
+    private int qwerty;
+    
+    @Column
+    private int occurances;
+    
 
     /**
      * @return the minLength
@@ -260,18 +276,57 @@ public class PasswordPolicy extends JpaBaseDomain implements java.io.Serializabl
         this.username = username;
     }
 
-    /**
-     * @return the simplePasswords
-     */
-    public String getSimplePasswords() {
-        return simplePasswords;
+
+    public int getHistory() {
+        return history;
     }
 
-    /**
-     * @param simplePasswords the simplePasswords to set
-     */
-    public void setSimplePasswords(String simplePasswords) {
-        this.simplePasswords = simplePasswords;
+    public void setHistory(int history) {
+        this.history = history;
+    }
+
+    public int getDictionary() {
+        return dictionary;
+    }
+
+    public void setDictionary(int dictionary) {
+        this.dictionary = dictionary;
+    }
+
+    public int getAlphabetical() {
+        return alphabetical;
+    }
+
+    public void setAlphabetical(int alphabetical) {
+        this.alphabetical = alphabetical;
+    }
+
+    public int getNumerical() {
+        return numerical;
+    }
+
+    public void setNumerical(int numerical) {
+        this.numerical = numerical;
+    }
+
+    public int getQwerty() {
+        return qwerty;
+    }
+
+    public void setQwerty(int qwerty) {
+        this.qwerty = qwerty;
+    }
+
+    public static long getSerialversionuid() {
+        return serialVersionUID;
+    }
+
+    public int getOccurances() {
+        return occurances;
+    }
+
+    public void setOccurances(int occurances) {
+        this.occurances = occurances;
     }
 
     public void check(String username, String newPassword, String oldPassword) throws PasswordPolicyException {
@@ -319,17 +374,14 @@ public class PasswordPolicy extends JpaBaseDomain implements java.io.Serializabl
         }
     }
 
-    /*
-     * (non-Javadoc)
-     * 
-     * @see java.lang.Object#toString()
-     */
     @Override
     public String toString() {
-        return "PasswordPolicy [minLength=" + minLength + ", maxLength=" + maxLength + ", lowerCase=" + lowerCase
-                + ", upperCase=" + upperCase + ", digits=" + digits + ", specialChar=" + specialChar + ", attempts="
-                + attempts + ", duration=" + duration + ", expiration=" + expiration + ", username=" + username
-                + ", simplePasswords=" + simplePasswords + "]";
+        return "PasswordPolicy [id=" + id + ", minLength=" + minLength + ", maxLength=" + maxLength + ", lowerCase="
+                + lowerCase + ", upperCase=" + upperCase + ", digits=" + digits + ", specialChar=" + specialChar
+                + ", attempts=" + attempts + ", duration=" + duration + ", expiration=" + expiration + ", username="
+                + username + ", history=" + history + ", dictionary=" + dictionary + ", alphabetical=" + alphabetical
+                + ", numerical=" + numerical + ", qwerty=" + qwerty + "]";
     }
 
+  
 }

+ 6 - 1
maxkey-core/src/main/java/org/maxkey/persistence/db/PasswordPolicyRowMapper.java

@@ -38,7 +38,12 @@ public class PasswordPolicyRowMapper implements RowMapper<PasswordPolicy> {
         passwordPolicy.setDuration(rs.getInt("DURATION"));
         passwordPolicy.setExpiration(rs.getInt("EXPIRATION"));
         passwordPolicy.setUsername(rs.getInt("USERNAME"));
-        passwordPolicy.setSimplePasswords(rs.getString("SIMPLEPASSWORDS"));
+        passwordPolicy.setHistory(rs.getInt("HISTORY"));
+        passwordPolicy.setDictionary(rs.getInt("DICTIONARY"));
+        passwordPolicy.setAlphabetical(rs.getInt("ALPHABETICAL"));
+        passwordPolicy.setNumerical(rs.getInt("NUMERICAL"));
+        passwordPolicy.setQwerty(rs.getInt("QWERTY"));
+        passwordPolicy.setOccurances(rs.getInt("OCCURANCES"));
         return passwordPolicy;
     }
 

+ 36 - 10
maxkey-core/src/main/java/org/maxkey/persistence/db/PasswordPolicyValidator.java

@@ -15,11 +15,13 @@ import org.maxkey.constants.ConstantsPasswordSetType;
 import org.maxkey.constants.ConstantsProperties;
 import org.maxkey.constants.ConstantsStatus;
 import org.maxkey.constants.ConstantsTimeInterval;
+import org.maxkey.crypto.password.PasswordGen;
 import org.maxkey.domain.PasswordPolicy;
 import org.maxkey.domain.UserInfo;
 import org.maxkey.util.StringUtils;
 import org.maxkey.web.WebConstants;
 import org.maxkey.web.WebContext;
+import org.passay.CharacterOccurrencesRule;
 import org.passay.CharacterRule;
 import org.passay.DictionaryRule;
 import org.passay.EnglishCharacterData;
@@ -64,7 +66,7 @@ public class PasswordPolicyValidator {
     private static final String PASSWORD_POLICY_KEY = "PASSWORD_POLICY_KEY";
     private static final String LOCK_USER_UPDATE_STATEMENT = "UPDATE MXK_USERINFO SET ISLOCKED = ?  , UNLOCKTIME = ? WHERE ID = ?";
 
-    private static final String PASSWORD_POLICY_SELECT_STATEMENT = "SELECT ID,MINLENGTH,MAXLENGTH,LOWERCASE,UPPERCASE,DIGITS,SPECIALCHAR,ATTEMPTS,DURATION,EXPIRATION,USERNAME,SIMPLEPASSWORDS FROM MXK_PASSWORD_POLICY ";
+    private static final String PASSWORD_POLICY_SELECT_STATEMENT = "SELECT * FROM MXK_PASSWORD_POLICY ";
 
     private static final String UNLOCK_USER_UPDATE_STATEMENT = "UPDATE MXK_USERINFO SET ISLOCKED = ? , UNLOCKTIME = ? WHERE ID = ?";
 
@@ -97,20 +99,28 @@ public class PasswordPolicyValidator {
             if(passwordPolicy.getUpperCase()>0) {
                 passwordPolicyRuleList.add(new CharacterRule(EnglishCharacterData.UpperCase, passwordPolicy.getUpperCase()));
             }
+            
             if(passwordPolicy.getLowerCase()>0) {
                 passwordPolicyRuleList.add(new CharacterRule(EnglishCharacterData.LowerCase, passwordPolicy.getLowerCase()));
             }
+            
             if(passwordPolicy.getDigits()>0) {
                 passwordPolicyRuleList.add(new CharacterRule(EnglishCharacterData.Digit, passwordPolicy.getDigits()));
             }
+            
             if(passwordPolicy.getSpecialChar()>0) {
                 passwordPolicyRuleList.add(new CharacterRule(EnglishCharacterData.Special, passwordPolicy.getSpecialChar()));
             }
+            
             if(passwordPolicy.getUsername()>0) {
                 passwordPolicyRuleList.add(new UsernameRule());
             }
             
-            if(passwordPolicy.getSimplePasswords().length()>0 ) {
+            if(passwordPolicy.getOccurances()>0) {
+                passwordPolicyRuleList.add(new CharacterOccurrencesRule(passwordPolicy.getOccurances()));
+            }
+            
+            if(passwordPolicy.getDictionary()>0 ) {
                 try {
                     ClassPathResource dictFile= 
                             new ClassPathResource(
@@ -201,9 +211,15 @@ public class PasswordPolicyValidator {
                                 );
         }
 
+        //initial password need change
+        if(userInfo.getLoginCount()<=0) {
+            WebContext.getSession().setAttribute(WebConstants.CURRENT_LOGIN_USER_PASSWORD_SET_TYPE,
+                    ConstantsPasswordSetType.INITIAL_PASSWORD);
+        }
+        
         if (userInfo.getPasswordSetType() != ConstantsPasswordSetType.PASSWORD_NORMAL) {
             WebContext.getSession().setAttribute(WebConstants.CURRENT_LOGIN_USER_PASSWORD_SET_TYPE,
-                    userInfo.getPasswordSetType());
+                        userInfo.getPasswordSetType());
             return true;
         } else {
             WebContext.getSession().setAttribute(WebConstants.CURRENT_LOGIN_USER_PASSWORD_SET_TYPE,
@@ -232,12 +248,6 @@ public class PasswordPolicyValidator {
             }
         }
         
-        //initial password need change
-        if(userInfo.getLoginCount()<=0) {
-            WebContext.getSession().setAttribute(WebConstants.CURRENT_LOGIN_USER_PASSWORD_SET_TYPE,
-                    ConstantsPasswordSetType.INITIAL_PASSWORD);
-        }
-
         return true;
     }
    
@@ -316,7 +326,23 @@ public class PasswordPolicyValidator {
        }
    }
    
-   
+   public String generateRandomPassword() {
+       getPasswordPolicy();
+       PasswordGen passwordGen = new PasswordGen(
+               Math.round(
+                       (
+                               passwordPolicy.getMaxLength() + 
+                               passwordPolicy.getMinLength()
+                       )/2
+                  )
+               );
+       
+       return passwordGen.gen(
+               passwordPolicy.getLowerCase(), 
+               passwordPolicy.getUpperCase(), 
+               passwordPolicy.getDigits(), 
+               passwordPolicy.getSpecialChar());
+   }
    
    public void setPasswordPolicy(PasswordPolicy passwordPolicy) {
     this.passwordPolicy = passwordPolicy;

+ 1 - 1
maxkey-core/src/test/java/org/maxkey/crypto/password/PasswordPolicyValidatorTest.java

@@ -16,7 +16,7 @@ public class PasswordPolicyValidatorTest {
          passwordPolicy.setUpperCase(2);
          passwordPolicy.setSpecialChar(1);
          passwordPolicy.setUsername(1);
-         passwordPolicy.setSimplePasswords("admin,1qaz,2wsx,123456,12345678,1234567890");
+         passwordPolicy.setDictionary(0);
         PasswordPolicyValidator passwordPolicyValidator =new PasswordPolicyValidator();
         
         passwordPolicyValidator.setPasswordPolicy(passwordPolicy);

+ 4 - 0
maxkey-persistence/src/main/java/org/maxkey/persistence/service/UserInfoService.java

@@ -181,6 +181,10 @@ public class UserInfoService extends JpaBaseService<UserInfo> {
 		return false;
 	}
 	
+	public String randomPassword() {
+	    return passwordPolicyValidator.generateRandomPassword();
+	}
+	
 	public void changePasswordProvisioning(UserInfo userInfo) {
 	    if(userInfo.getPassword()!=null && !userInfo.getPassword().equals("")) {
     	    ChangePassword changePassword=new ChangePassword();

+ 7 - 6
maxkey-web-manage/src/main/java/org/maxkey/web/contorller/UserInfoController.java

@@ -42,7 +42,6 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.beans.propertyeditors.CustomDateEditor;
-import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.stereotype.Controller;
 import org.springframework.validation.BindingResult;
 import org.springframework.web.bind.WebDataBinder;
@@ -50,7 +49,6 @@ import org.springframework.web.bind.annotation.InitBinder;
 import org.springframework.web.bind.annotation.ModelAttribute;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.servlet.ModelAndView;
@@ -68,12 +66,8 @@ public class UserInfoController {
 	@Autowired
 	@Qualifier("userInfoService")
 	private UserInfoService userInfoService;
-	
-	@Autowired
-	private PasswordEncoder passwordEncoder;
 
 	
-	
 	/**
 	 * 查询用户列表
 	 * @param user
@@ -164,6 +158,13 @@ public class UserInfoController {
 		return userInfo;
 	}
 	
+	
+    @ResponseBody
+    @RequestMapping(value = "/randomPassword")
+    public String randomPassword() {
+        return userInfoService.randomPassword();
+    }
+	   
 	/**
 	 * 修改用户
 	 * @param userInfo

+ 8 - 1
maxkey-web-manage/src/main/resources/messages/message.properties

@@ -99,7 +99,12 @@ login.passwordpolicy.attempts=\u767B\u5F55\u5C1D\u8BD5\u6B21\u6570
 login.passwordpolicy.duration=\u81EA\u52A8\u89E3\u9664
 login.passwordpolicy.expiration=\u8FC7\u671F\u65F6\u95F4
 login.passwordpolicy.username=\u5305\u542B\u7528\u6237\u540D
-login.passwordpolicy.simplepasswords=\u7B80\u5355\u5BC6\u7801
+login.passwordpolicy.dictionary=\u7B80\u5355\u5BC6\u7801\u5B57\u5178
+login.passwordpolicy.history=\u5386\u53F2\u5BC6\u7801\u6B21\u6570
+login.passwordpolicy.alphabetical=\u5B57\u6BCD\u5E8F\u5217\u7B56\u7565
+login.passwordpolicy.numerical=\u6570\u5B57\u5E8F\u5217\u7B56\u7565
+login.passwordpolicy.qwerty=\u952E\u76D8\u7B56\u7565
+login.passwordpolicy.occurances=\u5B57\u7B26\u91CD\u590D\u6B21\u6570
 
 
 login.social.link=\u7ED1\u5B9A
@@ -429,6 +434,8 @@ button.text.cancel=\u53D6\u6D88
 button.text.add.member=\u65B0\u589E\u6210\u5458
 button.text.delete.member=\u5220\u9664\u6210\u5458
 button.text.generate=\u751F\u6210
+button.text.view=\u67E5\u770B
+button.text.hidden=\u9690\u85CF
 
 log.loginhistory.id=\u7F16\u53F7
 log.loginhistory.sessionId=\u4F1A\u8BDD

+ 8 - 1
maxkey-web-manage/src/main/resources/messages/message_en.properties

@@ -101,7 +101,12 @@ login.passwordpolicy.attempts=attempts
 login.passwordpolicy.duration=duration
 login.passwordpolicy.expiration=expiration
 login.passwordpolicy.username=username
-login.passwordpolicy.simplepasswords=simplepasswords
+login.passwordpolicy.dictionary=Dictionary
+login.passwordpolicy.history=History
+login.passwordpolicy.alphabetical=ALPHABETICAL sequences
+login.passwordpolicy.numerical=NUMERICAL sequences
+login.passwordpolicy.qwerty=QWERTY sequences
+login.passwordpolicy.occurances=Occurances
 
 
 login.social.link=Link
@@ -428,6 +433,8 @@ button.text.cancel=Cancel
 button.text.add.member=Ddd member
 button.text.delete.member=Delete member
 button.text.generate=Generate
+button.text.view=View
+button.text.hidden=Hidden
 
 
 log.loginhistory.id=id

+ 8 - 1
maxkey-web-manage/src/main/resources/messages/message_zh_CN.properties

@@ -99,7 +99,12 @@ login.passwordpolicy.attempts=\u767B\u5F55\u5C1D\u8BD5\u6B21\u6570
 login.passwordpolicy.duration=\u81EA\u52A8\u89E3\u9664
 login.passwordpolicy.expiration=\u8FC7\u671F\u65F6\u95F4
 login.passwordpolicy.username=\u5305\u542B\u7528\u6237\u540D
-login.passwordpolicy.simplepasswords=\u7B80\u5355\u5BC6\u7801
+login.passwordpolicy.dictionary=\u7B80\u5355\u5BC6\u7801\u5B57\u5178
+login.passwordpolicy.history=\u5386\u53F2\u5BC6\u7801\u6B21\u6570
+login.passwordpolicy.alphabetical=\u5B57\u6BCD\u5E8F\u5217\u7B56\u7565
+login.passwordpolicy.numerical=\u6570\u5B57\u5E8F\u5217\u7B56\u7565
+login.passwordpolicy.qwerty=\u952E\u76D8\u7B56\u7565
+login.passwordpolicy.occurances=\u5B57\u7B26\u91CD\u590D\u6B21\u6570
 
 
 login.social.link=\u7ED1\u5B9A
@@ -429,6 +434,8 @@ button.text.cancel=\u53D6\u6D88
 button.text.add.member=\u65B0\u589E\u6210\u5458
 button.text.delete.member=\u5220\u9664\u6210\u5458
 button.text.generate=\u751F\u6210
+button.text.view=\u67E5\u770B
+button.text.hidden=\u9690\u85CF
 
 log.loginhistory.id=\u7F16\u53F7
 log.loginhistory.sessionId=\u4F1A\u8BDD

+ 78 - 14
maxkey-web-manage/src/main/resources/templates/views/config/passwordpolicy/passwordpolicy.ftl

@@ -122,6 +122,79 @@
 									<div class="row">
 										<div class="col-md-6">
 											<div class="form-group row">
+												<label class="col-sm-3 col-form-label"><@locale code="login.passwordpolicy.occurances" />:</label>
+												<div class="col-sm-9">
+													<input  required="" class="form-control" type="text" id="occurances" name="occurances" value="${model.occurances}" />
+												</div>
+											</div>
+										</div>
+										
+										<div class="col-md-6">
+											<div class="form-group row">
+												<label class="col-sm-3 col-form-label"><@locale code="login.passwordpolicy.username" />:</label>
+												<div class="col-sm-9">
+													<select  class="form-control"   id="username" name="username"  >
+														<option  <#if 1==model.username>selected</#if>  value="1"><@locale code="common.text.status.enabled"/></option>
+														<option  <#if 0==model.username>selected</#if>  value="0"><@locale code="common.text.status.disabled"/></option>
+													</select>
+												</div>
+											</div>
+										</div>
+									</div>
+									<div class="row">
+										<div class="col-md-6">
+											<div class="form-group row">
+												
+												<label class="col-sm-3 col-form-label"><@locale code="login.passwordpolicy.alphabetical" />:</label>
+												<div class="col-sm-9">
+													<select  class="form-control"   id="alphabetical" name="alphabetical"  >
+														<option  <#if 1==model.alphabetical>selected</#if>  value="1"><@locale code="common.text.status.enabled"/></option>
+														<option  <#if 0==model.alphabetical>selected</#if>  value="0"><@locale code="common.text.status.disabled"/></option>
+													</select>
+												</div>
+											</div>
+										</div>
+										<div class="col-md-6">
+											<div class="form-group row">
+												<label class="col-sm-3 col-form-label"><@locale code="login.passwordpolicy.numerical" />:</label>
+												<div class="col-sm-9">
+													<select  class="form-control"   id="numerical" name="numerical"  >
+														<option  <#if 1==model.numerical>selected</#if>  value="1"><@locale code="common.text.status.enabled"/></option>
+														<option  <#if 0==model.numerical>selected</#if>  value="0"><@locale code="common.text.status.disabled"/></option>
+													</select>
+												</div>
+											</div>
+										</div>
+									</div>
+									<div class="row">
+										<div class="col-md-6">
+											<div class="form-group row">
+												
+												<label class="col-sm-3 col-form-label"><@locale code="login.passwordpolicy.qwerty" />:</label>
+												<div class="col-sm-9">
+													<select  class="form-control"   id="qwerty" name="qwerty"  >
+														<option  <#if 1==model.qwerty>selected</#if>  value="1"><@locale code="common.text.status.enabled"/></option>
+														<option  <#if 0==model.qwerty>selected</#if>  value="0"><@locale code="common.text.status.disabled"/></option>
+													</select>
+												</div>
+											</div>
+										</div>
+										<div class="col-md-6">
+											<div class="form-group row">
+												
+												<label class="col-sm-3 col-form-label"><@locale code="login.passwordpolicy.dictionary" />:</label>
+												<div class="col-sm-9">
+													<select  class="form-control"   id="dictionary" name="dictionary"  >
+														<option  <#if 1==model.dictionary>selected</#if>  value="1"><@locale code="common.text.status.enabled"/></option>
+														<option  <#if 0==model.dictionary>selected</#if>  value="0"><@locale code="common.text.status.disabled"/></option>
+													</select>
+												</div>
+											</div>
+										</div>
+									</div>
+									<div class="row">
+										<div class="col-md-6">
+											<div class="form-group row">
 												<label class="col-sm-3 col-form-label"><@locale code="login.passwordpolicy.attempts" />:</label>
 												<div class="col-sm-9">
 													<input  required="" class="form-control" type="text" id="attempts" name="attempts" value="${model.attempts}" />
@@ -148,29 +221,20 @@
 										</div>
 										<div class="col-md-6">
 											<div class="form-group row">
-												<label class="col-sm-3 col-form-label"><@locale code="login.passwordpolicy.username" />:</label>
+												<label class="col-sm-3 col-form-label"><@locale code="login.passwordpolicy.history" />:</label>
 												<div class="col-sm-9">
-													<select  class="form-control"   id="username" name="username"  >
-														<option  <#if 1==model.username>selected</#if>  value="1"><@locale code="common.text.status.enabled"/></option>
-														<option  <#if 0==model.username>selected</#if>  value="0"><@locale code="common.text.status.disabled"/></option>
-													</select>
+													<input  required="" class="form-control" type="text" id="history" name="history"  value="${model.history!}" />
 												</div>
 											</div>
 										</div>
 									</div>
 
 									<div class="row">
-										<div class="col-md-12">
-											<div class="form-group m-b-20">
-												<label   style="float: left;" for="simplePasswords"><@locale code="login.passwordpolicy.simplepasswords" />:</label>
-												<textarea  required="" id="simplePasswords" name="simplePasswords"  class="form-control" >${model.simplePasswords!}</textarea>
-											</div>
-										</div>
-									</div>
-									<div class="row">
-										<div class="col-md-3">
+										<div class="col-md-4"></div>
+										<div class="col-md-4">
 											<button type="submit" class="button btn-primary btn btn-common btn-block mr-3"    id="submitBtn" ><@locale code="button.text.save" /></button>
 										</div>
+										<div class="col-md-4"></div>
 									</div>
 									
 								</form>

+ 13 - 0
maxkey-web-manage/src/main/resources/templates/views/index.ftl

@@ -0,0 +1,13 @@
+<!DOCTYPE HTML >
+<html xmlns="http://www.w3.org/1999/xhtml">
+	<head>
+		<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
+		<title>MaxKey</title>
+		<base href="<@base />"/>
+        <link rel="shortcut icon" type="image/x-icon" href="<@base />/static/images/favicon.ico"/>
+		<link type="text/css" rel="stylesheet" href="<@base url="/style.css"/>" />
+	</head>
+	<body>
+		<script type="text/javascript">window.top.location.href="<@basePath />/main";</script>
+	</body>
+</html>

+ 32 - 8
maxkey-web-manage/src/main/resources/templates/views/userinfo/changePassword.ftl

@@ -3,12 +3,33 @@
 <head>
 	<#include  "../layout/header.ftl"/>
 	<#include  "../layout/common.cssjs.ftl"/>
-<style   type="text/css">
-  .table th, .table td {
-    padding: .2rem;
-    vertical-align: middle;
-  }
-</style>
+	<style   type="text/css">
+	  .table th, .table td {
+	    padding: .2rem;
+	    vertical-align: middle;
+	  }
+	</style>
+
+	<script type="text/javascript">
+	<!--
+	$(function(){	
+		$("#generateSecret").on("click",function(){
+			$.post("<@base/>/userinfo/randomPassword/", {_method:"post",currTime:(new Date()).getTime()}, function(data) {
+				$("#password").val(data+"");
+				$("#confirmPassword").val(data+"");
+			}); 
+		});
+		$("#view").on("click",function(){
+			if($("#password").attr("type")=="text"){
+				$("#password").attr("type","password");
+			}else{
+				$("#password").attr("type","text");
+			}
+		});
+		
+	});
+	//-->
+	</script>
 </head>
 <body>
 
@@ -34,7 +55,8 @@
 			<tr>
 				<th><@locale code="login.password.newPassword" />:</th>
 				<td>
-					<input type="password" id="password" name="password"  required=""  class="form-control"  title="" value=""/>
+					<input type="password" id="password" name="password"  required=""  class="form-control"  title="" value="" width="80%"/>
+					
 				</td>
 			</tr>
 			<tr>
@@ -46,8 +68,10 @@
 			<tr>
 				<td colspan="2"  class="center">
 					<input id="_method" type="hidden" name="_method"  value="post"/>
+		    		<input id="generateSecret" type="button" class="button btn btn-warning mr-3" style="width:100px"  value="<@locale code="button.text.generate"/>"/>
+		    		<input id="view" type="button" class="button btn btn-info mr-3" style="width:100px"  value="<@locale code="button.text.view"/>"/>
 		    		<input class="button btn btn-primary mr-3"  style="width:100px"  type="submit"    id="submitBtn" value="<@locale code="button.text.save" />"/>
-					
+		    		
 				</td>
 			</tr>
 		</tbody>

+ 4 - 3
maxkey-web-maxkey/src/main/java/org/maxkey/web/endpoint/IndexEndpoint.java

@@ -69,11 +69,12 @@ public class IndexEndpoint {
 		
 		UserInfo userInfo=WebContext.getUserInfo();
 		modelAndView.addObject("model", userInfo);
-		if(passwordSetType==ConstantsPasswordSetType.PASSWORD_EXPIRED){
+		
+		if(passwordSetType==ConstantsPasswordSetType.PASSWORD_EXPIRED||
+                passwordSetType==ConstantsPasswordSetType.MANAGER_CHANGED_PASSWORD){
 			modelAndView.setViewName("passwordExpired");
 			return  modelAndView;
-		}else if(passwordSetType==ConstantsPasswordSetType.INITIAL_PASSWORD||
-				 passwordSetType==ConstantsPasswordSetType.MANAGER_CHANGED_PASSWORD){
+		}else if(passwordSetType==ConstantsPasswordSetType.INITIAL_PASSWORD){
 			modelAndView.setViewName("passwordInitial");
 			return  modelAndView;
 		}