EasyText, EasyLicense 的作者, https://github.com/EasyHelper Good Good Study,Day Day Up.

 

注册和登录还有那个加密的密码

假设你在设计自己的系统的时候采用的是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层中的方法,那么这些客户端都需要先将密码进行加密,然后调用服务。

image

现在需要增加php客户端,android 客户端。于是变成了:

image

所以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);       
    }
}

posted @ 2012-07-09 06:47  LoveJenny  阅读(9017)  评论(25编辑  收藏  举报
EasyText, EasyLicense 的作者, https://github.com/EasyHelper Good Good Study,Day Day Up.