You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by ja...@apache.org on 2007/09/07 06:58:36 UTC
svn commit: r573458 - in /ofbiz/trunk: applications/securityext/config/
framework/common/src/org/ofbiz/common/login/ framework/security/config/
framework/security/entitydef/
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"