Author: jaz
Date: Thu Sep 6 21:58:35 2007 New Revision: 573458 URL: http://svn.apache.org/viewvc?rev=573458&view=rev Log: implementation (from Anil Patel) to support restricting changed passwords to not allow the use of a previous password (the length of tracking is configurable in security.properties) Modified: ofbiz/trunk/applications/securityext/config/SecurityextUiLabels.properties ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LoginServices.java ofbiz/trunk/framework/security/config/security.properties ofbiz/trunk/framework/security/entitydef/entitygroup.xml ofbiz/trunk/framework/security/entitydef/entitymodel.xml Modified: ofbiz/trunk/applications/securityext/config/SecurityextUiLabels.properties URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/securityext/config/SecurityextUiLabels.properties?rev=573458&r1=573457&r2=573458&view=diff ============================================================================== --- ofbiz/trunk/applications/securityext/config/SecurityextUiLabels.properties (original) +++ ofbiz/trunk/applications/securityext/config/SecurityextUiLabels.properties Thu Sep 6 21:58:35 2007 @@ -56,6 +56,7 @@ loginevents.password_hint_is=The Password Hint is: ${passwordHint}. # ${errorMessage} = Error Description loginevents.error_accessing_password=Error accessing password: ${errorMessage}. +loginevents.error_accessing_password_change_history=Error accessing password change history: ${errorMessage}. loginevents.user_with_the_username_not_found=A user with the username "${userLoginId}" was not found, please re-enter. loginevents.no_primary_email_address_set_contact_customer_service=No Primary Email Address has been set, please contact customer service. loginevents.problems_with_configuration_contact_customer_service=Problems with configuration; please contact customer service. @@ -98,6 +99,7 @@ loginservices.password_or_verify_missing=Password or verify password missing. loginservices.password_did_not_match_verify_password=Password did not match verify password. loginservices.password_must_be_least_characters_long=Password must be at least ${minPasswordLength} characters long. +loginservices.password_must_be_different_from_last_passwords=Password cannot be one of your last ${passwordChangeHistoryLimit} passwords. loginservices.password_may_not_equal_username=Password may not equal the Username. loginservices.password_hint_may_not_contain_password=Password hint may not contain the password. Modified: ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LoginServices.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LoginServices.java?rev=573458&r1=573457&r2=573458&view=diff ============================================================================== --- ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LoginServices.java (original) +++ ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LoginServices.java Thu Sep 6 21:58:35 2007 @@ -28,6 +28,8 @@ import javax.transaction.Transaction; +import javolution.util.FastList; + import org.ofbiz.base.crypto.HashCrypt; import org.ofbiz.base.util.Debug; import org.ofbiz.base.util.UtilDateTime; @@ -37,10 +39,15 @@ import org.ofbiz.entity.GenericDelegator; import org.ofbiz.entity.GenericEntityException; import org.ofbiz.entity.GenericValue; +import org.ofbiz.entity.condition.EntityConditionList; +import org.ofbiz.entity.condition.EntityExpr; +import org.ofbiz.entity.condition.EntityOperator; import org.ofbiz.entity.model.ModelEntity; import org.ofbiz.entity.serialize.XmlSerializer; import org.ofbiz.entity.transaction.GenericTransactionException; import org.ofbiz.entity.transaction.TransactionUtil; +import org.ofbiz.entity.util.EntityFindOptions; +import org.ofbiz.entity.util.EntityListIterator; import org.ofbiz.security.Security; import org.ofbiz.service.DispatchContext; import org.ofbiz.service.ModelService; @@ -340,7 +347,47 @@ } return result; } - + + private static void createUserLoginPasswordHistory(GenericDelegator delegator,String userLoginId, String currentPassword) throws GenericEntityException{ + int passwordChangeHistoryLimit = 0; + try { + passwordChangeHistoryLimit = Integer.parseInt(UtilProperties.getPropertyValue("security.properties", "password.change.history.limit", "0")); + } catch (NumberFormatException nfe) { + //No valid value is found so don't bother to save any password history + passwordChangeHistoryLimit = 0; + } + if(passwordChangeHistoryLimit == 0 || passwordChangeHistoryLimit < 0){ + // Not saving password history, so return from here. + return; + } + List exprs = FastList.newInstance(); + EntityFindOptions efo = new EntityFindOptions(); + efo.setResultSetType(EntityFindOptions.TYPE_SCROLL_INSENSITIVE); + exprs.add(new EntityExpr("userLoginId", EntityOperator.EQUALS, userLoginId)); + List orderBy = UtilMisc.toList("-fromDate"); + EntityListIterator eli = delegator.findListIteratorByCondition("UserLoginPasswordHistory", new EntityConditionList(exprs, EntityOperator.AND),null, null, orderBy,efo); + Timestamp nowTimestamp = UtilDateTime.nowTimestamp(); + GenericValue pwdHist; + if((pwdHist = (GenericValue) eli.next()) !=null){ + // updating password so set end date on previous password in history + pwdHist.set("thruDate", nowTimestamp); + pwdHist.store(); + // check if we have hit the limit on number of password changes to be saved. If we did then delete the oldest password from history. + eli.last(); + int rowIndex = eli.currentIndex(); + if(rowIndex==passwordChangeHistoryLimit){ + eli.afterLast(); + pwdHist = (GenericValue) eli.previous(); + pwdHist.remove(); + } + } + // save this password in history + GenericValue userLoginPwdHistToCreate = delegator.makeValue("UserLoginPasswordHistory", UtilMisc.toMap("userLoginId", userLoginId,"fromDate", nowTimestamp)); + boolean useEncryption = "true".equals(UtilProperties.getPropertyValue("security.properties", "password.encrypt")); + userLoginPwdHistToCreate.set("currentPassword", useEncryption ? getPasswordHash(currentPassword) : currentPassword); + userLoginPwdHistToCreate.create(); + } + /** Creates a UserLogin *@param ctx The DispatchContext that this service is operating in *@param context Map containing the input parameters @@ -421,6 +468,7 @@ try { userLoginToCreate.create(); + createUserLoginPasswordHistory(delegator,userLoginId, currentPassword); } catch (GenericEntityException e) { Debug.logWarning(e, "", module); Map messageMap = UtilMisc.toMap("errorMessage", e.getMessage()); @@ -493,7 +541,6 @@ } List errorMessageList = new LinkedList(); - if (newPassword != null && newPassword.length() > 0) { checkNewPassword(userLoginToUpdate, currentPassword, newPassword, newPasswordVerify, passwordHint, errorMessageList, adminUser, locale); @@ -509,6 +556,7 @@ try { userLoginToUpdate.store(); + createUserLoginPasswordHistory(delegator,userLoginId, newPassword); } catch (GenericEntityException e) { Map messageMap = UtilMisc.toMap("errorMessage", e.getMessage()); errMsg = UtilProperties.getMessage(resource,"loginservices.could_not_change_password_write_failure", messageMap, locale); @@ -732,6 +780,38 @@ errorMessageList.add(errMsg); } + } + + int passwordChangeHistoryLimit = 0; + try { + passwordChangeHistoryLimit = Integer.parseInt(UtilProperties.getPropertyValue("security.properties", "password.change.history.limit", "0")); + } catch (NumberFormatException nfe) { + //No valid value is found so don't bother to save any password history + passwordChangeHistoryLimit = 0; + } + Debug.logInfo(" checkNewPassword passwordChangeHistoryLimitpasswordChangeHistoryLimitpasswordChangeHistoryLimit" + passwordChangeHistoryLimit, module); + if(passwordChangeHistoryLimit > 0 ){ + Debug.logInfo(" checkNewPassword Checking of user is tyring to use old password " + passwordChangeHistoryLimit, module); + GenericDelegator delegator = userLogin.getDelegator(); + String newPasswordHash = newPassword; + if (useEncryption) { + newPasswordHash = LoginServices.getPasswordHash(newPassword); + } + try { + List pwdHistList = delegator.findByAnd("UserLoginPasswordHistory", UtilMisc.toMap("userLoginId",userLogin.getString("userLoginId"),"currentPassword",newPasswordHash)); + Debug.logInfo(" checkNewPassword pwdHistListpwdHistList " + pwdHistList.size(), module); + if(pwdHistList.size() >0){ + Map messageMap = UtilMisc.toMap("passwordChangeHistoryLimit", passwordChangeHistoryLimit); + errMsg = UtilProperties.getMessage(resource,"loginservices.password_must_be_different_from_last_passwords", messageMap, locale); + errorMessageList.add(errMsg); + Debug.logInfo(" checkNewPassword errorMessageListerrorMessageList " + pwdHistList.size(), module); + } + } catch (GenericEntityException e) { + Debug.logWarning(e, "", module); + Map messageMap = UtilMisc.toMap("errorMessage", e.getMessage()); + errMsg = UtilProperties.getMessage(resource,"loginevents.error_accessing_password_change_history", messageMap, locale); + } + } if (!UtilValidate.isNotEmpty(newPassword) || !UtilValidate.isNotEmpty(newPasswordVerify)) { Modified: ofbiz/trunk/framework/security/config/security.properties URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/security/config/security.properties?rev=573458&r1=573457&r2=573458&view=diff ============================================================================== --- ofbiz/trunk/framework/security/config/security.properties (original) +++ ofbiz/trunk/framework/security/config/security.properties Thu Sep 6 21:58:35 2007 @@ -29,6 +29,11 @@ # -- disable the account after this many logins -- max.failed.logins=3 +# -- number of password change to be saved in UserLoginPasswordHistory. +# -- passwords saved in history of userLoginId will not be allowed to be reused. +# -- 0 to not save history at all +password.change.history.limit=0 + # -- disable the account for this many minutes (if 0, then indefinate) -- login.disable.minutes=5 Modified: ofbiz/trunk/framework/security/entitydef/entitygroup.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/security/entitydef/entitygroup.xml?rev=573458&r1=573457&r2=573458&view=diff ============================================================================== --- ofbiz/trunk/framework/security/entitydef/entitygroup.xml (original) +++ ofbiz/trunk/framework/security/entitydef/entitygroup.xml Thu Sep 6 21:58:35 2007 @@ -32,6 +32,7 @@ <!-- ========================================================= --> <entity-group group="org.ofbiz" entity="UserLogin" /> + <entity-group group="org.ofbiz" entity="UserLoginPasswordHistory" /> <entity-group group="org.ofbiz" entity="UserLoginHistory" /> <entity-group group="org.ofbiz" entity="UserLoginSession" /> Modified: ofbiz/trunk/framework/security/entitydef/entitymodel.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/security/entitydef/entitymodel.xml?rev=573458&r1=573457&r2=573458&view=diff ============================================================================== --- ofbiz/trunk/framework/security/entitydef/entitymodel.xml (original) +++ ofbiz/trunk/framework/security/entitydef/entitymodel.xml Thu Sep 6 21:58:35 2007 @@ -77,6 +77,20 @@ <field name="successiveFailedLogins" type="numeric"></field> <prim-key field="userLoginId"/> </entity> + <entity entity-name="UserLoginPasswordHistory" + package-name="org.ofbiz.security.login" + never-cache="true" + title="User Login Password History Entity"> + <field name="userLoginId" type="id-vlong-ne"></field> + <field name="fromDate" type="date-time"></field> + <field name="thruDate" type="date-time"></field> + <field name="currentPassword" type="short-varchar"></field> + <prim-key field="userLoginId"/> + <prim-key field="fromDate"/> + <relation type="one" fk-name="USER_LPH_USER" rel-entity-name="UserLogin"> + <key-map field-name="userLoginId"/> + </relation> + </entity> <entity entity-name="UserLoginHistory" package-name="org.ofbiz.security.login" never-cache="true" |
Free forum by Nabble | Edit this page |