很久没有写PHP代码了,尤其是Lumen,我是Lumen的忠实用户,从Lumen出来我就把它作为我API的主要框架。但是说到API,不得不说一个概念:“前后端分离”。现在越来越多的团队采用前后端分离的方式,完全解放了前端的优势,让后端更专注于数据输出。此处不讨论这方面的讨论。深入研究可以参考一些文章:https://segmentfault.com/a/11...由于前后端分离,后台侧重于接口API的输出。那个时候,Lumen的出现,Lumen就是为RESTfulAPI而生的:DecidedlyLaravel。令人愉快的最小。闪电般快速的微服务和API以您期望的优雅交付。使用Lumen作为接口框架必须解决一个核心问题:如何实现“Authentication”。虽然Lumen和Laravel使用相同的底层类库实现来进行用户认证,但是由于Lumen是面向无状态API开发的,不支持会话,所以默认配置是不同的。Lumen必须使用无状态机制来实现,例如API令牌(Token)。我们看一下Lumen官网提供的例子:useIlluminate\Http\Request;$app->get('/post/{id}',['middleware'=>'auth',function(Request$request,$id){$user=Auth::user();$user=$request->user();//}]);使用中间件:'middleware'=>'auth',我们看auth中间件函数:$app->routeMiddleware(['auth'=>App\Http\Middleware\Authenticate::class,]);关联了Authenticate类,我们看一下Authenticate的handle函数:/***Handleanincomingrequest。**@param\Illuminate\Http\Request$request*@param\Closure$next*@paramstring|null$guard*@returnmixed*/publicfunctionhandle($request,Closure$next,$guard=null){如果($this->auth->guard($guard)->guest()){returnresponse('Unauthorized.',401);}返回$next($request);}会先判断$this->auth->guard($guard)->guest()。我们继续跟进代码进入AuthManager:/***尝试从本地缓存中获取守卫。**@param字符串$name*@return\Illuminate\Contracts\Auth\Guard|\Illuminate\Contracts\Auth\StatefulGuard*/publicfunctionguard($name=null){$name=$name?:$this->getDefaultDriver();返回isset($this->guards[$name])?$this->guards[$name]:$this->guards[$name]=$this->resolve($name);}$name默认传入=null,所以我们看$this->getDefaultDriver():/***获取默认的认证驱动名称。**@returnstring*/publicfunctiongetDefaultDriver(){return$this->app['config']['auth.defaults.guard'];}这是默认的配置config:从Lumen源码中可以看出Lumen默认的认证方式“api”。我们来看看Laravel默认的认证方式:Laravel默认使用“web”方式,web方式使用session进行用户认证。这也很好地说明了Lumen的无状态。那么我们就需要了解一下Lumen是如何使用“api”来进行用户认证的。AuthServiceProvider位于app/Providers文件夹中,并且此文件中只有一个Auth::viaRequest调用。viaRequest将在系统需要认证时被调用。此方法接受匿名函数作为参数。在这个匿名函数中,可以任意解析AppUser并返回,或者解析失败返回null,如:/***为应用程序启动认证服务。**@returnvoid*/publicfunctionboot(){//在这里您可以定义您希望用户如何为您的Lumen//应用程序进行身份验证。//接收传入请求实例的回调应该返回一个用户实例或null。您可以通过API令牌或任何其他必要的方法自由获取//User实例。$this->app['auth']->viaRequest('api',function($request){if($request->input('api_token')){returnUser::where('api_token',$request->input('api_token'))->first();}});让我们看一下viaRequest函数:/***注册一个新的基于回调的请求守卫。**@paramstring$driver*@paramcallable$callback*@return$this*/publicfunctionviaRequest($driver,callable$callback){return$this->extend($driver,function()use($callback){$guard=newRequestGuard($callback,$this->app['request'],}$this->createUserProvider());$this->app->refresh('request',$guard,'setRequest');返回$guard;});}这里关键的是RequestGuard,这种类型的内核数:/***获取当前认证的用户。**@return\Illuminate\Contracts\Auth\Authenticatable|null*/publicfunctionuser(){//如果我们已经检索到当前请求的用户,我们可以立即将其返回。我们不想在每次调用此方法时都获取用户数据,因为那样会非常慢。如果(!is_null($this->user)){返回$this->user;}返回$this->user=call_user_func($this->callback,$this->request,$this->getProv伊德());}这个是判断是否获取到用户信息,主要是调用回调函数,这个函数就是我们从viaRequest传入的:function($request){if($request->input('api_token')){returnUser::where('api_token',$request->input('api_token'))->first();而这只是一个验证用户的例子,判断请求是否传入了api_token参数,通过User模型直接匹配查找得到User或null,当然在实际开发中,我们不能简单的获取api_token直接关联数据库查找用户信息。在API开发中,用户认证是数据安全的核心和前提。目前常用的用户认证方式有两种:JWT和OAuth2。接下来只是简单了解Lumen的“用户认证”。接下来就是学习“JWT”,看看如何使用JWT有效的对用户进行认证,保证接口信息被合法用户更安全的访问。附件:Json网络令牌(JWT),是一种基于JSON的开放标准(RFC7519),用于在Web应用程序环境之间传输声明。令牌设计紧凑且安全,特别适用于分布式站点中的单点登录(SSO)场景。JWT的语句一般用于在身份提供者和服务提供者之间传递经过认证的用户身份信息,从而从资源服务器获取资源,也可以添加一些其他业务逻辑所需要的附加语句信息。令牌也可以直接用于认证或加密。《待续》coding01期待您的持续关注
