Laravel不使用Bcrypt加密

Reading time ~1 minute

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

挂载网络文件夹后网络故障时文件操作命令卡死

挂载 NFS 或者 Samba 的时候,经常会由于网络故障导致挂载好的链接断掉。此时如果尝试进行 ls、cd、df 等各种命令,只要与此目录沾上边,就会卡住。如果使用了类似 oh-my-zsh 这种配置的,只要在网络目录中,弹出命令提示符前就会直接卡住。这个时候第一反应就是...… Continue reading

路由折腾记 第四弹

Published on September 02, 2017