在laravel中,默认的Auth使用的密码加密方式是Bcrypt散列密码,然后很多时候,我们想使用自己定义的加密方式,出于作业要求,我这次是要使用SHA256加密,当然,我们完全可以不使用Auth来自己实现,不过这里为了方便,我还是想直接使用Auth。
既然要使用Auth,那么我们就要对Auth模块进行扩展,在laravel的官方文档上,感觉讲的并不是很清楚,各种麻烦,于是最后自己查着资料研究了半天,得到了如下解决方案:
首先是官网上说的最详细的,也是最麻烦的方法,我们可以写一个自己的实现了UserProviderInterface接口的UserProvider类,然后通过Auth::extend来注册我们的驱动,最后到app/config/auth.php修改配置即可,具体可以看官网,这个方法还是说的比较详细的。
然后第二个方案是我正在采用的方案,通过研究laravel的框架代码发现,在AuthManager的createEloquentProvider中,我们可以发现如下代码:
/**
* Create an instance of the Eloquent user provider.
*
* @return IlluminateAuthEloquentUserProvider
*/
protected function createEloquentProvider()
{
$model = $this->app['config']['auth.model'];
return new EloquentUserProvider($this->app['hash'], $model);
}
很显然,就是在这里选择了hash算法,那么我们将最后这句话的参数替换成我们想要的hash算法就可以了。
这里的app['hash']里面是一个BcryptHasher,于是我们可以仿照BcryptHasher写出一个Sha256Hasher:
use IlluminateHashingHasherInterface;
class Sha256Hasher implements HasherInterface {
/**
* Hash the given value.
*
* @param string $value
* @param array $options
* @return string
*
* @throws RuntimeException
*/
public function make($value, array $options = array())
{
$hash = hash('sha256', $value);
return $hash;
}
/**
* Check the given plain value against a hash.
*
* @param string $value
* @param string $hashedValue
* @param array $options
* @return bool
*/
public function check($value, $hashedValue, array $options = array())
{
return $this->make($value) === $hashedValue;
}
/**
* Check if the given hash has been hashed using the given options.
*
* @param string $hashedValue
* @param array $options
* @return bool
*/
public function needsRehash($hashedValue, array $options = array())
{
return false;
}
}
然后我们还是采用extend的方式添加自己的驱动:
Auth::extend('sha256', function() {
return new IlluminateAuthEloquentUserProvider(new ExtensionsHashingSha256Hasher(), 'SecurityModelsUser');
});
或者也可以不用Eloquent,直接使用database:
Auth::extend('sha256', function() {
$connection = DB::connection();
// When using the basic database user provider, we need to inject the table we
// want to use, since this is not an Eloquent model we will have no way to
// know without telling the provider, so we'll inject the config value.
$table = Config::get('auth.table');
return new IlluminateAuthDatabaseUserProvider($connection, new ExtensionsHashingSha256Hasher(), $table);
});
最后,我们还是在app/config/auth.php修改配置为sha256即可。
第三种方案应该算是官方文档中的基于IoC的扩展,和第二个有点类似,都是要实现一个Sha256Hasher,不过接下来要做的是就完全不一样了。
首先再添加一个Sha256HashServiceProvider,继承IlluminateSupportServiceProvider,以将Sha256Hasher注册为hash组件,也就是将上面所提到的app['hash']直接给替换掉,Sha256HashServiceProvider可以仿照HashServiceProvider来实现,代码如下:
use IlluminateSupportServiceProvider;
class Sha256HashServiceProvider extends ServiceProvider {
/**
* Indicates if loading of the provider is deferred.
*
* @var bool
*/
protected $defer = true;
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->app->bindShared('hash', function() { return new Sha256Hasher; });
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return array('hash');
}
}
最后,我们修改app/config/app.php中的providers,将其中下面一行删除:
'IlluminateHashingHashServiceProvider',
替换成自己刚实现的Sha256HashServiceProvider,即完成了散列方式的切换,这种方法意味着,laravel中所有使用到app['hash']来进行散列的全都会被替换成我们自己的散列方式,包括使用Hash::的时候。