Laravel 5.4 下面Custom Auth的一些备忘

Laravel 提供了强大的用户登录功能。建立起Application之后直接 php artisan make:auth 就可以建立起一个最基本的基于用户邮箱密码登录的MiddleWare。
但是有时候,当我们需要进行二次开发,当数据库并不在本地,用户信息都需要通过API获取的时候,我们就需要按照laravel的接口自己来写用户的登录了。
这次我们需要从一个由Yar 的rpc api提供的接口中去获取用户信息。

配置自定义的用户登录Provider

1
2
3
4
5
//config/auth.php
'providers' => [
'users' => [
'driver' => 'yar_provider',
],

注册该Provider

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
namespace App\Auth;
use Auth;
use App\Auth\YarUserProvider;
use Illuminate\Support\ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot()
{
Auth::provider('yar_provider', function($app, array $config) {
return new YarUserProvider();
});
}

}

可以看到我们需要返回一个YarUserProvider的object。在这个Provider中,我们需要完成的任务就是调用API获取用户信息并完成用户的验证。

实现custom的Provider

首先看一下我们需要实现的接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

namespace Illuminate\Contracts\Auth;

interface UserProvider {

public function retrieveById($identifier);
public function retrieveByToken($identifier, $token); //用于没有session的情况,比如API的http的header。这次无视。
public function updateRememberToken(Authenticatable $user, $token); // 暂时不管
public function retrieveByCredentials(array $credentials);
public function validateCredentials(Authenticatable $user, array $credentials);

}

retrieveById($identifier)一般用户当我们刷新页面的时候,我们的app从session中获取用户id,然后通过我们的实现,用这个id来获取用户信息。
这次我们需要做的仅仅是调用Yar的API(传递用户id,返回用户信息的API)。

retrieveByCredentials(array $credentials);用户用户登录时候提供用户名(或者邮箱),我们来通过这个用户名获取用户信息,以供validateCredentials(Authenticatable $user, array $credentials);来进行用户的验证。

我们看到我们都需要返回一个Authenticatable $user的东西。 这个接口要求我们去实现很多user model的功能,比如获取密码之类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

namespace Illuminate\Contracts\Auth;

interface Authenticatable {

public function getAuthIdentifierName();
public function getAuthIdentifier();
public function getAuthPassword();
public function getRememberToken();
public function setRememberToken($value);
public function getRememberTokenName();

}

自己统统去实现自然也是可以的,不过Laravel已经提供了一个叫GenericUser的类来帮助我们啦。我们直接把从API获取的用户信息来生成一个GenericUser的对象就行了。

想这样。 当然由于GenericUser需要有些特殊的attribute,所以当没有的时候我们可以找适当的项目不上。比如下面的例子,我们需要提供一个name的attribute。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public function validateCredentials(\Illuminate\Contracts\Auth\Authenticatable $user, array $credentials)
{
// we'll assume if a user was retrieved, it's good
$attributes = $this->client->Auth(['username' => $credentials["username"], 'passwd'=>$credentials["password"]]);
if($attributes["status"] != 1)
{
return null;
}
else
{
$attributes["data"]["name"] = $attributes["data"]["firstname"].$attributes["data"]["lastname"];
return new GenericUser($attributes["data"]);
}
}

具体实现就不贴了,由于API本身不是很优雅,上层实现也不是那么优雅就是了。