打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
【auth】扩展Auth功能
参考:http://blog.chedushi.com/archives/9456

框架本身提供了很多常用的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的的附加串

在加入这两个字段后,我们来考虑两个情景:

第一个情景就是注册(或是修改密码)的时候, 第二个情景是验证的时候,这两个情景的流程如下图所示:

左侧是情景一的图示,右侧是情景二的图示,由于在数据库中不存储密码的明文,同时采用了每个用户一种单独Salt的方案,在数据库被攻破后,窃密者必须付出极大的成本才可能破解出用户的密码明文,并且方法只能是为每种Salt都重新建立一份字典,在这样的成本下,我们可以认为这种方案是非常安全的。

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

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

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

UserProviderInterface.php

DatabaseUserProvider.php

EloquentUserProvider.php

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

UserProviderInterface

interface UserProviderInterface {    public function retrieveById($identifier);    public function retrieveByToken($identifier, $token);    public function updateRememberToken(UserInterface $user, $token);    public function retrieveByCredentials(array $credentials);    public function validateCredentials(UserInterface $user, array $credentials);}

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

Custom UserProvider

<?php namespace Illuminate\Auth;class TaskPoolEloquentUserProvider extends EloquentUserProvider {  public function __construct($model)  {    $this->model = $model;  }  /**   * Validate a user against the given credentials.   *   * @param  \Illuminate\Auth\UserInterface  $user   * @param  array  $credentials   * @return bool   */  public function validateCredentials(UserInterface $user, array $credentials)  {    $plain = $credentials['password'];    $authPassword = $user->getAuthPassword();    return $authPassword['psw_hash'] === md5($plain.$authPassword['psw_salt']);  }}

通过继承和覆盖的方式,我们改写了原有Eloquent驱动的验证逻辑。根据官方文档的描述,这个文件可以放在任意地方,也可以使用任意命名空间,在这里就不过多叙述了。

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

UserInterface

interface UserInterface {  public function getAuthIdentifier();  public function getAuthPassword();  public function getRememberToken();  public function setRememberToken($value);  public function getRememberTokenName();}

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

最后一步就是将这个扩展注册到框架当中,打开这个文件:

app/start/global.php

在其中添加如下代码:

global.php
Auth::extend('taskpooleloquent', function($app) {    $provider =  new \Illuminate\Auth\TaskPoolEloquentUserProvider('User');    return $provider;});

之后,就可以在Config中的Auth配置文件中使用你自己定义的这个驱动了


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
API接口JWT方式的Token认证(上),服务器(Laravel)的实现
Redis PHP通用类
使用Flask设计带认证token的RESTful API接口[翻译]
编程语言thinkphp框架下实现登录、注册、找回密码功能,thinkphp找回密码_PHP教程
实录分享 | 微服务访问安全设计方案全探索
【Laravel系列7.4】安全相关
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服