假設你在設計自己的系統的時候采用的是MVC架構。例如
也許可能有很多童鞋會這樣設計Service和Model.
service:
public class AccountService
{
public bool Login(string userName, string password)
{
// insert into account values(userName,password);
return true;
}
public bool Register(string userName, string password)
{
// select count(*) from account where userName = userName and password = password;
return true;
}
}
然后model是這樣的:
public class UserModel
{
public bool Login(string userName, string password)
{
string encryptedPassword = password.MD5();
AccountService accountService = new AccountService();
return accountService.Login(userName, encryptedPassword);
}
public bool Register(string userName, string password)
{
string encryptedPassword = password.MD5();
AccountService accountService = new AccountService();
return accountService.Register(userName, encryptedPassword);
}
}
很明顯,這段代碼完成了注冊和登錄的任務,並且密碼也是以加密的形式保存的。
比如123456 =>e10adc3949ba59abbe56e057f20f883e
當然有些人會認為密碼不夠安全,然后進行兩次md5,或者是加salt,加userName,等。
下面拋一個問題:聰明的你認為上面的這種設計安全嗎???
如果你認為上面的代碼很安全,那么你就很需要往下面看看了。
Service和Model這樣設計的缺點:
1:加密在model層中做,如果你有多個界面的話,我指的是客戶端(asp.net,android,php…).然后這些客戶端調用的是service層中的方法,那么這些客戶端都需要先將密碼進行加密,然后調用服務。
現在需要增加php客戶端,android 客戶端。於是變成了:
所以asp.net Model, php Model, android Model 都需要進行相同的加密,並且你需要保證這三個平台所加密的字符串是相同的,
比如123456 =>在這三個Model層中都必須被加密為:e10adc3949ba59abbe56e057f20f883e
這是一個很惡心的問題,不過幸運的是這三個平台的md5 加密出來的是一樣的,如果不一樣的話,可能是需要設置下字符編碼。
2:上面的這個缺點雖然比較嚴重,但還不是最致命的,這個設計最致命的地方在於Service層沒有進行加密驗證,如果你獲取了用戶的用戶名和密碼的話,直接登錄就OK了。
假設A用戶的用戶名為LoveJenny,密碼為123456.
在數據庫中儲存的值是LoveJenny,e10adc3949ba59abbe56e057f20f883e。
對於hacker而言,他偶然獲取了用戶名:LoveJenny,密碼:e10adc3949ba59abbe56e057f20f883e
首先他嘗試試用LoveJenny 和e10adc3949ba59abbe56e057f20f883e 來調用Service服務登錄系統,f**k,Service 沒有驗證,於是他便登錄了,他不需要知道LoveJenny的密碼是123456,同時也不需要理解e10adc3949ba59abbe56e057f20f883e 是怎樣生成的,他只需要輸入用戶名:LoveJenny,然后密碼:e10adc3949ba59abbe56e057f20f883e 來調用服務就可以登錄了。
最后如果你還是認為:
1:他是怎樣偶然得到LoveJenny和e10adc3949ba59abbe56e057f20f883e 的?
這點我無法回答,因為我也不知道hacker會怎樣獲取,不過可以肯定的是,只要你的系統不是很安全的話,應該是可以獲取的。
2:多個model中做驗證沒什么大不了的?
這點我持反對意見,首先它違反了don’t repeat your self 原則,其次,把本該服務層中做的事情放到
model層來做,最后假設你的系統有多個平台的話,很郁悶的哦。
3:就算知道用戶名和數據庫密碼,他又怎樣繞過model來調用服務呢?
這個。。。,我還是不知道,不過萬一你的服務是暴露在外網上的,如果你老板想讓你做個開放平台,如果你的服務器被hacker掉了。。。,當然如果很多很多。。,借口
不要認為安全是個組件,到時候拿過來用就行了,個人認為在開發和設計的時候,就應該考慮安全,當然絕對的安全是不可能的,我們只能保證我們該做的都做了,而不是把這些安全漏洞歸咎於上面的幾點,或者是更多點。
最后的最后我貼上我認為正確的設計:
Service層:
public class AccountService
{
public bool Login(string userName, string password)
{
string encryptedPassword = getEncryptedString(password);
// insert into account values(userName,encryptedPassword);
return true;
}
public bool Register(string userName, string password)
{
string encryptedPassword = getEncryptedString(password);
// select count(*) from account where userName = userName and password = encryptedPassword;
return true;
}
}
Model層:
public class UserModel
{
public bool Login(string userName, string password)
{
AccountService accountService = new AccountService();
return accountService.Login(userName, password);
}
public bool Register(string userName, string password)
{
AccountService accountService = new AccountService();
return accountService.Register(userName, password);
}
}