在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::的时候。