当前位置: 首页 > 后端技术 > PHP

Lumen用户认证JWT,源码解读

时间:2023-03-29 19:54:08 PHP

最近的一个PHP项目,上一个项目是用ThinkPHP做的,因为很早就听说了Laravel的大名,所以进入了Laravel的官网,无意中发现了Lumen。我的项目提供了API,所以我选择了Lumen,因为它是Laravel的简化版。看了几天Laravel的文档,也总结了一些自己的经验,不权威:1.Larave的核心是服务容器,而服务容器是DependencyInjection的主要功能2.各部分Laravel的大部分功能都是以组件的形式提供的。需要注射什么?下面进入JWT认证的正题。感谢学习Lumen用户认证(二)——使用jwt-auth插件这篇文章对我有帮助。如何进行用户认证?根据Laravel文档描述,Laravel提供了用户认证的接口。它的核心是一个守卫(Guard)和一个提供者(Provider)。守卫定义如何验证用户,提供者定义如何检索用户。首先创建项目lumennewjwt-demo,然后进入jwt-demo目录,执行composerrequiretymon/jwt-auth:1.0.0-rc.2,在项目根目录下创建config文件夹,将vender/laravel中将auth.php复制到config目录下,auth.php文件内容如下:然后修改boostrap/app.php文件,添加如下配置修改路由文件routers/web.php必须使用jwt.auth中间件,然后在Controllers目录下新建App/AuthController.php文件,内容如下:修改app/Exceptions/Handler.php文件,然后访问域名/auth/home,用浏览器,结果如下:现在我们看看401是怎么从源码中来的?这里定义的路由需要经过jwt.auth中间件。下一步这个中间件定义在哪里?可以看到在LumenServiceProvider里面有$this->app->routeMiddleware($this->middlewareAlias)这样的一句,可以看到这里定义了一个路由中间件,名字叫jwt.auth,对应的是Tymon\JWTAuth\Http\Middleware\Authenticate类。如果你查看这个类的实现,你可以看到它是通过$this->authenticate方法验证的。,所以现在看这个方法的实现可以看到这里有两个方法,checkForToken用来验证token是否存在,不存在则抛出异常,存在则输入$this->auth->parseToken()->authenticate()用于验证token是否合法。这里不讨论如何验证token是否存在。看他是怎么验证token是否合法的。JWTAuth类的以下方法可以从跟踪代码的以下方法中看出执行情况。首先从payload中获取id值,然后通过id获取用户,如果获取成功返回false,token无效,否则返回获取到的用户,token合法,然后跟踪获取代码用户,最后进入JWTGuard类的如下方法$this->provider就是我们在config/auth.php中配置的eloquent,对应的类是EloquentUserProvider,我们看一下它的retrieveById方法,实现如下,这里我们已经是从数据库中找用户了,在实际研发中,我们可能会有自己的数据库查找逻辑,所以我们只能实现自己的Provider,然后将JWTGuard中的Provider替换掉,那么这一步我们应该怎么做呢?在bootstrap/app.php中,有这么一句$app->register(Tymon\JWTAuth\Providers\LumenServiceProvider::class);,我们可以看看LumenServiceProvider的源码,可以看到有这样一个方法,我们可以看一下,可以看到这里传入了Provider,那么我们看一下AuthManager的createUserProvider方法。程序会先读取Provider的配置信息,也就是auth.php中的这么一部分,然后在customProviderCreators中判断是否有对应的Guard,如果存在,则根据driver创建自定义的Provider。否则判断驱动是datebase还是eloquent。如果不正确,将抛出异常。否则,将创建DatebaseProvider或EloquentProvider。按照这样一段代码,我们只需要在auth.php中添加配置自己的驱动,然后在customProviderCreators中注入我们自己的Provider实现类即可。那么怎么注入呢,AuthManager中有这么一个方法那么怎么自定义Provider就解决了,现在来实践一下,自定义Provider代码如下。参考EloquentUserProvider和DatebaseUserProvider可知需要实现UserProvider接口。为了方便,我直接继承了DatebaseUserProvider,重写了retrieveById方法,默认返回true。首先修改auth.php中provider的驱动为my,然后InjectMyJWTUserProvider,在app/Jwt目录下新建MyLumenServiceProvider,代码如下,最后在boostrap/app.php中添加rRegister的LumenServiceProvider改为MyLumenServiceProvider。至此JWT还有一个生成用户认证返回token的过程