最近在尝试使用Laravel框架进行一些实际开发,框架本身提供了很多常用的Web应用的机制和库,虽然很好用,但是却不能包容我预期的设计,比如Auth模块,该模块提供了两种很基本的验证驱动,一个是Database,使用QueryBuilder来与数据库进行交互,另一个是Eloquent ORM,是采用其内置的ORM库来进行数据库交互(感觉类似于.Net中的EF),但是不论采取哪种驱动,都存在同样的局限性:

必须采用内置的Hash方案对入库的密码进行保护

这一局限使得原本系统设计中的MD5 + Salt方案受到了阻挠,尽管实现会稍显麻烦,但我仍然认为这种方案更适合于我的项目,因此我参考了Laravel文档中扩展章节所述的Auth模块扩展以及网上查阅的一些资料,来对原框架进行修改,使其能够支持有我自己定义的验证驱动。

首先介绍我所考虑使用的MD5 + Salt方案的具体设计:
数据库中不应该存储密码明码应该是一个基本安全常识,通常的方案是采用MD5算法对密码进行Hash,再存入数据库,从而避免数据库泄露之后,用户的敏感数据也随之泄露,但是随着时间发展,人们存储的MD5的字典已经越来越庞大,对于一些弱口令(例如12345678、passw0d,不足够长的纯数字或字母串),即便是在不可逆算法MD5 Hash过后再入库,对于拥有字典的人而言,仍然与明文无异,对于有经验的人而言,可能看到25d55ad283aa400af464c76d713c07ad,脑子里就已经浮现了12345678这串数字了。于是对密码加Salt的想法就孕育而生,如果说用户自己设定的密码很简单,那么不妨让系统来帮他进行加强,而Salt就是在原来的密码上加的那一点“佐料”,只要能够保证无论曾经的密码多么简单,只要加完Salt之后,字典中就无法直接找到这个Hash对应的原文,那么这个方案就算是成功了。

首先,用户数据库我们需要两个字段:

psw_hash:用来存储Hash过后的密码
psw_salt:用来存储帮助Hash的的附加串

在加入这两个字段后,我们来考虑两个情景:
第一个情景就是注册(或是修改密码)的时候, 第二个情景是验证的时候,这两个情景的流程如下图所示:
1
左侧是情景一的图示,右侧是情景二的图示,由于在数据库中不存储密码的明文,同时采用了每个用户一种单独Salt的方案,在数据库被攻破后,窃密者必须付出极大的成本才可能破解出用户的密码明文,并且方法只能是为每种Salt都重新建立一份字典,在这样的成本下,我们可以认为这种方案是非常安全的。

那么接下来的问题就是,如何在Laravel框架中扩展出这一机制?根据文档,我们可以先找到这个目录:

/vender/laravel/framework/src/illuminate/Auth

这个目录就是Laravel框架所提供的Auth库地址,其中我们首先关注:

UserProviderInterface.php
DatabaseUserProvider.php
EloquentUserProvider.php

第一个文件是一个接口,后面两个文件中的类实现了第一个文件中的接口,而后面两个类就是前文所提到的,默认Auth库所支持的两种验证驱动,我们从他们都实现的UserProviderInterface入手,下面的代码是从文档中摘录的精简过的接口定义代码:

可以看到,都是和验证过程有关的方法,也就是说我们只需要实现这些接口方法,就可以添加自己的验证驱动,而从实际使用出发,我们在项目中会使用Eloquent ORM来产生相关实体的数据模型,所以我们无须完全重写驱动,只需要改写EloquentUserProvider中的部分方法即可,在这里我们的代码如下所示:

之后,注意到验证逻辑中的第一个参数UserInterface $user,这个参数告诉我们,支持Auth的User模型应当实现UserInterface,这个接口的定义文件也在这个目录下,简化的代码如下:

这些都很容易理解,都是简单的getter和setter,只需要让自己的User模型类实现它就可以了。

通过继承和覆盖的方式,我们改写了原有Eloquent驱动的验证逻辑。根据官方文档的描述,这个文件可以放在任意地方,也可以使用任意命名空间,这里使用的是我们项目的名称。随后这个文件可以被放置在任意位置,只要在下面的目录中的这个配置文件:

app/config/global.php

中的addDirectories中添加你的目录,随后再在文件

composer.json

中的autoload加入你的目录,保存后再在项目根目录中执行命令:

即可。

最后一步就是将这个扩展注册到框架当中,打开这个文件:
app/start/global.php
在其中添加如下代码:

之后,就可以在Config中的Auth配置文件中使用你自己定义的这个驱动了~关于Laravel框架其实还有很多特性,我将会在实践中陆续进行整理并在这里分享。

说点什么

8 评论 在 "Laravel框架初识:扩展Auth功能"

  Subscribe  
最新 最旧 得票最多
提醒

感谢博主的这篇文章,帮助我自己写了自定义Hash方式的实现在5.3版本

我想就问问 怎么存明文!我的内网对接有一个程序是明文的!!!烦!

[…] 我谷歌了一下,还真让我找到了。转送:http://blueve.me/archives/898 […]

$authPassword = $user->getAuthPassword();
这里返回一个字符串 你如何得到一个数组?

psw_salt=md5(psw_str);
psw_hash=md5(psw_str+psw_salt);

用这种方法来生成psw_salt,是不是更方便一些
也不用存储psw_salt,也能满足每个用户的psw_salt是不同的