实现登陆逻辑至少涉及两个方面,登陆与注册

本文使用SQL语言的MySQL dialect

登陆(Log in)

登陆主要是实现将用户提交的含有用户名uname和密码passwd的表单提交给数据库对比,如果发现此条记录在数据库中存在且合法,则返回登陆成功,否则返回登陆失败,需要请求用户重新提交。

这边主要注意的是一个点,在查询的时候我们会使用SQL语句去数据库查询,一般想到的逻辑应该是去查询得到用户名对应的密码,然后再去对比用户提交的密码与数据库返回的密码是否一致。即使用了以下的SQL代码:

SELECT passwd FROM user_info WHERE uname = $UNAME;

在登陆成功情况下两者并无任何区别,但实际上这个方式有一个巨大的缺陷:在登陆失败时,这种数据处理方式割裂了“用户名输入错误”(此用户名不存在)与“查到用户名,但密码错误”两种情况。如果这两种不同的情况被以不同形式返回到前端(比如分别提示“用户名错误”或“密码错误”,那么就很容易被通过“撞库攻击”而“撞”出网站的许多用户的用户名,即使他们并不知道每个id的密码,这无疑方便了攻击者通过id暴力穷举或者使用密码字典的方式获取密码。

正确的处理方法应该是连着用户名和密码一起放入SQL语句里去查询,比如:

SELECT * FROM user_info WHERE uname = $UNAME AND passwd = $PASSWD;

然后通过执行了该语句之后是否具有返回数据的方式来判断用户试图登陆的账号密码对是否被注册且有效。如果成功,则结果同上,但是若登陆失败,那么它只能体现用户名和密码错误,安全性相对更高。

注册(Register)

注册的验证涉及三个步骤:

  • 验证提交的密码的合法性
  • 验证提交的username的唯一性
  • 插入提交的用户名与密码到数据库。

提交密码的合法性判断

无非是判断密码长度、判断是否含有不合法字符、判断密码格式是否合规。使用各种语言的字符串处理手段乃至正则表达式都可以直接实现,此处不再赘述。提供一个常见的网站密码格式要求:以字母开头,必须包含大/小写字母、数字、一般符号的至少三种,长度在8-64位之间。

提交的用户名的唯一性判断

可以通过SQL语言的SELECT语句,即查询语句来实现,比如:

SELECT * FROM user_info WHERE uname = $UNAME;

然后通过执行该语句后是否有查询到的数据来判断这个用户名是否被注册过,以决定是否要为此组提交的数据执行注册(即插入数据表)的操作。

值得一提的是,你可与为某一列设置UNIQUE来保证这列的数据一定不相同,此情况下,若插入重复的username将会导致MySQL抛出异常,需要对这一异常进行处理。

插入提交的数据到数据库

在我们确认用户提交的数据在数据库中不会出现问题之后,我们便可以把用户提交的键值对插入数据表中了。插入操作使用INSERT来实现,例如:

INSERT INTO user_info (uname, passwd) VALUES ($UNAME, $PASSWD);

此方法会把$UNAME与$PASSWD以一条新记录的方式插入到对于数据表中。一般在这种情况下,它便不再会出现插入异常了。