views:

566

answers:

3

I am struggling to figure out how I should override equals and get hashcode for a class I am writing using NHibernate.

Basic business scenario is that users cannot re-use the same password within a 90 day limit.

So I have a "user" that has many "historical passwords"... the user class was easy as I just use the login in the equals. Below is my HistoricalPassword class.

public class HistoricalPassword
{
    public virtual int HistoricalPasswordId { get; set; }
    public virtual User User { get; set; }
    public virtual DateTime ChangeDate { get; set; }
    public virtual string FormerPassword { get; set; }
}

I would say from a business sense that the combination of the User and the ChangeDate would give me equality. However... it does not seem correct to reference the user in the equals method (since for one thing that would cause a lazy load to happen)... and also from what I read using the PK of HistoricalPasswordId is a no-no as well.

Can anyone provide some advice on how they would override equals for this?

EDIT ::: I think I might have been a little misleading on the way I asked the question. I'm not confused on how to enforce the business rule of making sure the passwords are not reused... nor on how I know if two passwords are equal or are secure. What I really want to know is at the entity level specifically relating to NHibernate how would I override Equals for this object so that NHibenate does not end up with dupes in the session and/or cache. According to the NHibernate doc (https://www.hibernate.org/hib_docs/nhibernate/html/persistent-classes.html) I should override equals using Business key equality. In this case I'm just not sure if using the referenced object of User in the compare is a good idea.

+2  A: 

I wouldn't override Equals for this - you aren't asserting that these records are equal, merely that they reference the same password, aren't you?

Surely you just need an HQL or criteria query that gives you the historical passwords set within the last 90 days?

EDIT: Also you might want to check how you are storing your password. Plaintext passwords in the database are not a good idea. It may be that you have an NHibernate user type that is decrypting an encrypted password into the string property we can see, of course...

David M
Thanks for your quick reply... and concern over my security :)For sake of simplify lets assume my passwords are secure.But getting back to the issue... I feel like there is this ping pong match going back and forth on people saying YOU MUST override equals and gethashcode or else you are doomed using NHibernate as you will end up with dups in your session... and then there are just as many people saying don't bother overriding or just use the PK in the equality check... !!! yikes !!!
Todd
Equality of entity is the same as equality of primary key surely, so override Equals accordingly. But what you are talking about is not actual equality but some other sort of equivalence.
David M
A: 

I would regard the HistoricalPassword to be a value object, not an entity.

So, this means that it's 'ID' would be determined by the value of all its properties.

Frederik Gheysels
A: 

Couple of ways you could go about this.

If you want to do it using equality, then the user will be involved, specifically the PK of the user. Equality would be the user PK + the password. Date wouldn't matter. This probably over complicates things, however, and I probably wouldn't go about it this way.

Another way is to use just the password for equality, since that's what you are comparing against in the end. The user would only be used in the query, ditto the change date.

Do an HQL query to get the historical passwords where user = {user} and change date < (today - 90). this will return all of the passwords from the last 90 days for {user}. Once that problem is done, all you would need to do is compare the passwords to see if any match, since you have reduced your result set to only those passwords from the last 90 days for {user}.

Finally, as mentioned above, simply do an HQL query for {user} where date changed < 90 and password = {new password}. If you get any results back, you know that password has been used in the last 90 days.

Finally, as also was mentioned above, these comparisons all assume you're either playing with plaintext passwords or encrypting the new password for comparison against the old ones. Ether way, something has to be done to account for the security of the passwords.

Andy C.