IDEMPIERE-358 Login- how to make unique and safe - implement email login for monitor

This commit is contained in:
Juliana Corredor 2012-08-16 15:34:37 -05:00
parent e0b518164e
commit ca94ad6670
1 changed files with 52 additions and 69 deletions

View File

@ -36,6 +36,7 @@ import org.compiere.util.CCache;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.compiere.util.KeyNamePair;
import org.compiere.util.Msg;
import org.compiere.util.Secure;
import org.compiere.util.SecureEngine;
@ -173,80 +174,62 @@ public class MUser extends X_AD_User
return null;
}
boolean hash_password = MSysConfig.getBooleanValue(MSysConfig.USER_PASSWORD_HASH, false);
boolean email_login = MSysConfig.getBooleanValue(MSysConfig.USE_EMAIL_FOR_LOGIN, false);
ArrayList<KeyNamePair> clientList = new ArrayList<KeyNamePair>();
ArrayList<Integer> clientsValidated = new ArrayList<Integer>();
MUser retValue = null;
if (!hash_password)
{
int AD_Client_ID = Env.getAD_Client_ID(ctx);
String sql = "SELECT * FROM AD_User "
+ "WHERE COALESCE(LDAPUser, Name)=? " // #1
+ " AND ((Password=? AND (SELECT IsEncrypted FROM AD_Column WHERE AD_Column_ID=417)='N') " // #2
+ "OR (Password=? AND (SELECT IsEncrypted FROM AD_Column WHERE AD_Column_ID=417)='Y'))" // #3
+ " AND IsActive='Y' AND AD_Client_ID=?" // #4
;
PreparedStatement pstmt = null;
ResultSet rs = null;
try
{
pstmt = DB.prepareStatement (sql, null);
pstmt.setString (1, name);
pstmt.setString (2, password);
pstmt.setString (3, SecureEngine.encrypt(password));
pstmt.setInt(4, AD_Client_ID);
rs = pstmt.executeQuery ();
if (rs.next ())
{
retValue = new MUser (ctx, rs, null);
if (rs.next())
s_log.warning ("More then one user with Name/Password = " + name);
}
else
s_log.fine("No record");
StringBuffer where = new StringBuffer("Password IS NOT NULL AND ");
if (email_login)
where.append("EMail=?");
else
where.append("COALESCE(LDAPUser,Name)=?");
where.append(" AND")
.append(" EXISTS (SELECT * FROM AD_User_Roles ur")
.append(" INNER JOIN AD_Role r ON (ur.AD_Role_ID=r.AD_Role_ID)")
.append(" WHERE ur.AD_User_ID=AD_User.AD_User_ID AND ur.IsActive='Y' AND r.IsActive='Y') AND ")
.append(" EXISTS (SELECT * FROM AD_Client c")
.append(" WHERE c.AD_Client_ID=AD_User.AD_Client_ID")
.append(" AND c.IsActive='Y') AND ")
.append(" AD_User.IsActive='Y'");
List<MUser> users = new Query(ctx, MUser.Table_Name, where.toString(), null)
.setParameters(name)
.setOrderBy(MUser.COLUMNNAME_AD_User_ID)
.list();
if (users.size() == 0) {
s_log.saveError("UserPwdError", name, false);
return null;
}
for (MUser user : users) {
if (clientsValidated.contains(user.getAD_Client_ID())) {
s_log.severe("Two users with password with the same name/email combination on same tenant: " + name);
return null;
}
catch (Exception e)
{
s_log.log(Level.SEVERE, sql, e);
clientsValidated.add(user.getAD_Client_ID());
boolean valid = false;
if (hash_password) {
String hash = user.getPassword();
String salt = user.getSalt();
// always do calculation to confuse timing based attacks
if ( hash == null )
hash = "0000000000000000";
if ( salt == null )
salt = "0000000000000000";
valid = user.authenticateHash(password);
} else {
// password not hashed
valid = user.getPassword().equals(password);
}
finally
{
DB.close(rs, pstmt);
rs = null; pstmt = null;
}
} else {
String where = " COALESCE(LDAPUser,Name) = ? AND" +
" EXISTS (SELECT * FROM AD_User_Roles ur" +
" INNER JOIN AD_Role r ON (ur.AD_Role_ID=r.AD_Role_ID)" +
" WHERE ur.AD_User_ID=AD_User.AD_User_ID AND ur.IsActive='Y' AND r.IsActive='Y') AND " +
" EXISTS (SELECT * FROM AD_Client c" +
" WHERE c.AD_Client_ID=AD_User.AD_Client_ID" +
" AND c.IsActive='Y') AND " +
" AD_User.IsActive='Y'";
MUser user = MTable.get(ctx, MUser.Table_ID).createQuery( where, null).setParameters(name).firstOnly(); // throws error if username collision occurs
String hash = null;
String salt = null;
if (user != null )
{
hash = user.getPassword();
salt = user.getSalt();
}
// always do calculation to confuse timing based attacks
if ( user == null )
user = MUser.get(ctx, 0);
if ( hash == null )
hash = "0000000000000000";
if ( salt == null )
salt = "0000000000000000";
if ( user.authenticateHash(password) )
{
if (valid){
retValue=user;
}
}
}
return retValue;
} // get