laravel 框架扩展 Auth 认证,实现自定义 driver,guard
文章目录
起
最近研究 laravel 自带的认证,发现使用token认证方式的话,默认传值字段和数据库中字段名都是api_token
,这让我很不爽,laravel 这样的框架一定有什么自定义的途径,网上查询无果,那就自己看看源码吧。
寻
我们知道,认证其实就是调用Auth::guard()
来执行的,那我们不妨从这里开始看起。
自定义dirver配置项
我们知道Auth
是Illuminate/Auth/AuthManager.php
的alias,那我们打开这个文件,找到guard
后,发现判断用实际哪个guard的代码在方法resolve
中,其中有一段代码:
|
|
发现这个类中有一个数组customCreators
,这说明,我们是可以自定义driver的。也就是说,虽然config/auth.php
的guards
中说driver
只支持session
和token
,但实际上是可以自己扩展的。
那怎么扩展呢,顺藤摸瓜,发现class AuthManager
中有一个方法extend
:
|
|
这个方法就是给Auth添加自定义driver用的,那我们直接找个provider扩展一下Auth,把自己的driver添加进去就好。
我们可以先看一下默认的token driver是怎么写的:
|
|
就这么几行代码,在5.6以后TokenGuard
的构造函数是有4个参数的,原型如下
|
|
也就是说,我们把后两个参数传进去就可以了。那就开始搞起,例如在AppServiceProvider
的boot
方法中添加:
|
|
这样我们就有了一个新的driver——web-token
,config中我们就可以写:
|
|
这里发现我的provider也不是users,是因为我新建了一张表专门存token用,配置起来很方便,在同文件的providers
中添加如下配置即可:
|
|
但是这样一来,就产生了新的问题:我们在使用laravel的时候,总会使用类似Auth::id()
,Auth::user()
这样的方法,因为确实很方便,而我们的认证现在虽然没有问题了,但是因为跟user不是同表,这些方法现在不能用了,那怎么办呢?我们首先来解决第一个问题:
实现 Auth:id()
我们可以看一下框架带的User Model,发现其继承自Illuminate\Foundation\Auth\User
,顺藤摸瓜,我们发现他实现了三个接口:
|
|
这三个接口各有作用,比方说第一个AuthenticatableContract
,就是我们目前要实现的,因为其中有一个方法public function getAuthIdentifier();
,这个方法就是执行Auth::id()
时候会调用的。
第二个接口是授权时候用的,第三个是重置密码时候用的,这两个我们暂时不需要,那就等以后用到时候再说。
我们现在让Token Model实现第一个接口,方法的实现根据各自的情况有所不同,例如我的token表中,用户的id列名为user_id
,那我的方法就是这样子的:
|
|
而因为我实现了实体关系:
|
|
其他的一些方法可以这样写:
|
|
这样大体上第一个问题我们就解决了,接下来解决第二个问题。
实现 Auth:user()
首先,我们来找一下这个user()方法在哪里,看了AuthManager
以后发现,这个user()原来是调用的Guard中的方法,那怎么办呢?我们扩展一下TokenGuard吧。
新建一个php类继承于TokenGuard
,并重写user()
方法:
|
|
return null
并不会产生问题,这样会使Guard的check()
方法返回false,抛出AuthenticationException
异常,这与正常的逻辑是一致的。
这样我们就解决了Auth::user()
的问题,扩展类还可以解决一些其他的问题,例如在5.4版本中,$inputKey
和$storageKey
是直接写在构造函数中的,而不是参数穿进去的,扩展类也可以解决这个问题。
优化
因为使用用了新的Guard类,我们在provider中的代码也需要做一些修改,而同时,我们把字段名也写到config中,便于以后修改,优化后的代码如下:
|
|
这样基本就趋近于最终版本了。
尾
laravel 确实是一个庞大的框架,这次只涉及到了认证的问题,而未谈及授权,例如Auth::can()
这样的方法,现在也是不能使用的。
授权也是一个大头的问题,不同的需求采用的方式不尽相同,laravel也自带一套授权的机制,希望本篇文章可以达到一个抛砖引玉的作用,给小伙伴们一些启发。