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本身不是很优雅,上层实现也不是那么优雅就是了。