I do and I understand

用户认证

前期准备

Laravel的权限配置文件位于 config/auth.php,Laravel的认证组件由“guards”和“providers”组成,
Guard 通过 session 来维护用户登录的状态。Provider 是登录以及访问页面的时候获取用户的信息。本篇主要讲的是如何自定义Provider ,获取用户信息。

config/auth.php文件

Laravel提供了两种guard,web以及api,采取默认的web认证。在guards的web中,用了users提供者。接下来就需要注意了,我们自定义了服务提供者,就需要换到新的providers。首先,定义一个使用新驱动的provider:

1
2
3
4
5
6
 'providers' => [
'users' => [
'driver' => 'Focus', //名称自定义,这里为Focus
'model' => App\Models\User::class, //Model放在Models文件夹下
],
],

Notes: 默认提供了两种驱动database和eloquent,而这两种的提供者分别是DatabaseUserProvider和EloquentUserProvider,都处于laravel\framework\src\Illuminate\Auth文件夹下,实现了UserProvider,我们自定义的 Focus provider 也将实现UserProvider。

生成路由和视图

1
php artisan make:auth  //命令可快速生成认证所需要的路由和视图

Http/Controllers 和 resources/views下会相应生成控制器和视图
默认用的Email,我们用username

LoginController:
//添加此方法,返回username

1
2
3
public function username(){
return 'username';
}

login.blade.php:
将邮箱改为域账号,email 改为username

数据库

修改.env配置中的数据库信息。

1
php artisan make:model Models/User  // 使用命令创建User模型

默认User是继承Model的,需要修改。

1
2
3
4
5
6
7
8
9
use Illuminate\Foundation\Auth\User as Authenticatable;  //引入Authenticatable
class User extends Authenticatable
{
protected $table = 'employee';
protected $primaryKey = 'employee_id';

//can set all fields to user model
protected $guarded = [];
}

为什么要引入Authenticatable呢,是因为Authenticatable实现了Illuminate\Contracts\Auth\Authenticatable接口,而FocusUserProvider 需要用到接口的实现。

创建扩展

在app下新建 Extensions/FocusUserProvider 文件,参考DatabaseUserProvider和EloquentUserProvider,实现UserProvider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
namespace App\Extensions;

use App\Services\LdapValidator;
use Illuminate\Support\Str;
use Illuminate\Contracts\Auth\UserProvider;
use \Illuminate\Contracts\Auth\Authenticatable;

class LaravelUserProvider implements UserProvider {

protected $model;

public function __construct($model)
{
$this->model = $model;
}

//登录成功后,通过此方法获取用户信息,返回匹配该ID的 Authenticatable 实现
public function retrieveById($identifier) {

//此处可以将信息放入缓存,缓解数据库压力。
$model = $this->createModel();
return $model->newQuery()
->where($model->getAuthIdentifierName(), $identifier)
->first();
}

public function retrieveByToken($identifier, $token) {
}
public function updateRememberToken(Authenticatable $user, $token) {
}

//该方法可以根据账号名去查询数据库是否存在匹配的账号
public function retrieveByCredentials(array $credentials) {

if (empty($credentials)) {
return;
}

// First we will add each credential element to the query as a where clause.
// Then we can execute the query and, if we found a user, return it in a
// Eloquent User "model" that will be utilized by the Guard instances.
$query = $this->createModel()->newQuery();

foreach ($credentials as $key => $value) {
if (! Str::contains($key, 'password')) {
$query->where($key, $value);
}
}

return $query->first();
}

//该方法可以验证密码是否正确,因为我们是ldap登录,可以在此验证域账号
public function validateCredentials(Authenticatable $user, array $credentials) {

//LdapValidator类是为了验证域密码的,放在了app/Services,在上面已经引入
$Ldap = new LdapValidator($user->username, $credentials['password']);

return $Ldap->validatePassword();
}

/**
* Create a new instance of the model.
*
* @return \Illuminate\Database\Eloquent\Model
*/
public function createModel()
{
$class = '\\'.ltrim($this->model, '\\');

return new $class;
}

}

注册提供者

Laravel 提供了AuthServiceProvider, 我们可以在这里注册。

1
2
3
4
5
6
7
8
9
10
public function boot()
{
$this->registerPolicies();

//Focus为auth.php里面定义的驱动
Auth::provider('Focus', function($app, array $config){

return new FocusUserProvider ($config['model']);
});
}

下面就可以访问http://你的域名/login 登录系统