为了兼容minecraft的authme密码hash方式,我们不能使用laravel自带的BcryptHash。所以我们需要对登录流程进行一些修改。
首先我们来看原来的BcryptHash是在哪里使用的
#vendor\laravel\framework\src\Illuminate\Auth\CreatesUserProviders.php
/**
* Create an instance of the Eloquent user provider.
*
* @param array $config
* @return \Illuminate\Auth\EloquentUserProvider
*/
protected function createEloquentProvider($config)
{
return new EloquentUserProvider($this->app['hash'], $config['model']);
}
这里我们发现当创建默认的EloquentUserProvider时,laravel自带hash,也就是Bcrypt被作为参数传递了,所以我们就要想办法让这里不使用自带hash,而在这里直接更改是不行的,因为这是laravel的源码,我们是不能修改的。
我们转而把注意力放在自定义UserProvider上,自定义之后我们当然就能使用自己的hash方式了。下面是一个例子(http://laravelacademy.org/post/5974.html)
#app\Providers\AuthServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Auth;
use App\Extensions\RiakUserProvider;
use Illuminate\Support\ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* Register any application authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
Auth::provider('riak', function($app, array $config) {
// Return an instance of Illuminate\Contracts\Auth\UserProvider...
return new RiakUserProvider($app->make('riak.connection'));
});
}
}
但是这时候我们发现,其实我们完全还可以在这里继续使用EloquentUserProvider,因为我们的目的只是更改hash方式,只需要在上面实例化EloquentUserProvider的地方,将我们自己的Hash类作为第一个参数传递进去就好了。
首先,我们先写好我们自己的Hash类,根据EloquentUserProvider的源码,我们发现我们的Hash类必须是Illuminate\Contracts\Hashing\Hasher契约的实现,契约的源码如下
interface Hasher
{
/**
* Hash the given value.
*
* @param string $value
* @param array $options
* @return string
*/
public function make($value, array $options = []);
/**
* 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 = []);
/**
* 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 = []);
}
我们只需要补全上面的方法,实现这个接口即可,下面是我们自定义的AuthmeHasher
namespace App\Libraries\Hashing;
use Illuminate\Contracts\Hashing\Hasher as HasherContract;
class AuthmeHasher implements HasherContract{
/**
* Hash the given value.
*
* @param string $value
* @param array $options
* @return string
*/
public function make($value, array $options = []){
$p1 = '$SHA';
$p2 = str_random(16);
$p3 = hash('sha256', hash('sha256', $value) . $p2);
$hash = join('$',[$p1,$p2,$p3]);
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 = []){
if (strlen($hashedValue) === 0) {
return false;
}
$parts = explode('$', $hashedValue);
return count($parts) === 4
&& $parts[3] === hash('sha256', hash('sha256', $value) . $parts[2]);
}
/**
* 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 = []){
if (strlen($hashedValue) === 0) {
return false;
}
return $hashedValue;
}
}
这里由于不知道needsRehash方法该如何写,所以我直接返回了原先的hashedValue。具体这个文件的写法,我们也可以参考laravel默认的vendor\laravel\framework\src\Illuminate\Hashing\BcryptHasher.php
接下来就是最关键的部分了,我们将自己的AuthmeHash注入到EloquentUserProvider
#app\Providers\AuthServiceProvider.php
namespace App\Providers;
use Auth;
use Illuminate\Auth\EloquentUserProvider;
use App\Libraries\Hashing\AuthmeHasher;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
//使用authme的Hash来处理密码
Auth::provider('authme', function($app, array $config) {
return new EloquentUserProvider(new AuthmeHasher,$config['model']);
});
}
}
当然,最后别忘了设置config\auth.php下面的providers中driver为你上面在Auth::provider中声明的名字
/*
|--------------------------------------------------------------------------
| User Providers
|--------------------------------------------------------------------------
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| If you have multiple user tables or models you may configure multiple
| sources which represent each model / table. These sources may then
| be assigned to any extra authentication guards you have defined.
|
| Supported: "database", "eloquent"
|
*/
'providers' => [
'users' => [
'driver' => 'authme',
'model' => App\User::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
在最后还是说一句,学习Laravel阅读源码还是关键,文档的作用有的时候比较有局限性。本篇文章参考了http://blueve.me/archives/898的一些信息