问题
JAVA 8
I have a POJO class:
class User {
private String name;
private String password;
//... Getters / Setters ...
}
Which i will use as an entity class.
In the getter/setter for password
, I want to add decryption/encryption logic.
public String getPassword() {
return EncryptionFactory.decryption(password);
}
public void setPassword(String password) {
this.password = EncryptionFactory.encryption(password);
}
EncryptionFactory
is a utility class which encrypts/decrypt a String
.
My question is
Based on the General Java coding guidelines, if I add logic to alter password, does it break design or its a bad design?
While using it i got bad design feedback from my professors.
回答1:
From the wiki article on mutators:
Often a setter is accompanied by a getter (also known as an accessor), which returns the value of the private member variable
Since getters are intended for giving access to private field values, it would violate the principle of least astonishment: an exception could be thrown, the impl for EncrpytionFactory
may become invalid at some point, etc... When developers are expecting to simply access a value.
Whether you consider this bad design depends on how strict your design standards are. The best way to determine is to look at the cons:
- Unable to obtain encrypted password
- Forced to use
String
for plain-text password to store password (sincesetPassword
automatically encrypts) - Introduces the dependency of
EncrpytionFactory
within the type that containsget/setPassword
So in your specific case, it's bad design.
Although there are cases where it may be preferred by some developers. For example, if you had a Person#getAge() : int
but used a Date
property to manage the person's age:
class Person {
private Date dateOfBirth;
public int getAge() {
Date now = ...; //grab date/time right now
int age = ...; //calculate age using dateOfBirth and now
return age;
}
Some would argue that the calculation should be decoupled, or getAge
should be named calculateAge
.
From the wiki article:
Accessors conversely allow for synthesis of useful data representations from internal variables while keeping their structure encapsulated and hidden from outside modules. A monetary getAmount accessor may build a string from a numeric variable with the number of decimal places defined by a hidden currency parameter.
In your case, there is more to worry about.
Do you REALLY want to decrypt the password, as in, is there any reason to? Assuming you want to maintain security, there are safer ways to maintain a password.
Anytime you want to compare an entered password to a stored password, simply encrpyt the entered password and compare the results to the stored password.
If someone wants to "recover" their password, it would be a security risk to send the user their password in plain-text. This is why large businesses require you to reset your password if you forget it.
Lets say you wanted to keep the decryption.
Do you really need to decrypt everytime someone calls getPassword()
? What if someone wants the encrpyted value?
You should keep decryption separate from accessing. Seeing how you already have a EncryptionFactory
:
User user = ...;
String encryptedPassword = user.getPassword();
String decryptedPassword = EncryptionFactory.decryption(encryptedPassword);
There should only be few times where your password actually exists decrypted (some may argue it should never exist decrypted in memory). Point is, it should be completely optional.
The password should be set already encrypted:
String encryptedPassword = EncryptionFactory.encrpytion(...);
User user = ...;
user.setPassword(encryptedPassword);
It should be accessible in encrpyted form. You should never force security risks like this (decrypting a password), make it optional.
Lastly, if you must expose a decrypted getPassword
alternative, you should rename it to decryptPassword()
:
public String decryptPassword() {
return EncrpytionFactory.decryption(getPassword());
}
Although this introduces unneccesary coupling betweeing User
(or whatever type your'e using) and EncryptionFactory
.
You should really look deeper into the security aspects. You should not be maintaining decrypted passwords as String, and it's safest if no one but the user knows the password.
来源:https://stackoverflow.com/questions/44600536/is-it-bad-design-if-we-add-logic-in-getter-and-setter-of-entity-class