这段时间对laravel的路由解析流程很感兴趣,想要看看在整个路由解析流程中是否存在薄弱环节或者是可利用点。通过网上现有的分析文章对照着自己本地的环境调试了一波。感觉laravel在路由解析这块的安全性确实很高。(也有可能是因为没有太多输入点。。。)等考完试还要继续看看,现在先把我理解的记录下来,以便之后复习使用。
路由加载服务
在laravel中有一个特有的概念,称之为服务提供者。服务提供者的功能是完成laravel应用的引导启动。我的理解是通过服务提供者RouteServiceProvider可以加载某些已经内置于laravel中的模块。在这里,我们可以把路由加载理解为是一种服务。对应的存在一个服务提供者RouteServiceProvider
用于在laravel kernel中加载这一服务。只有在加载之后,我们才能获取已经在routes/web.php
文件中注册的路由。laravel框架入口文件是public/index.php
,该文件38行加载bootstrap/app.php
文件。在bootstrap/app.php
中实现laravel中常用服务的注册和启动。由于我们这里主要分析对于外部传入路由的解析,因此不对路由表的加载深入分析。我们只要知道通过包含bootstrap/app.php
文件,可以获取当前所有的已注册路由。
路由解析
继续看public/index.php
文件源码:
52行的作用只是实例化Illuminate\Contracts\Http\Kernel
这个类。往下走到54行才是我们需要深入研究的重点。$request = Illuminate\Http\Request::capture()
这一句代码的作用是返回http请求的一些参数。比如:GET参数,POST参数,FILES参数等等。我们把目光放在$kernel->handle
函数中。
在$kernel->handle
函数中,将解析的request
传入$this->sendRequestThroughRouter
函数。从$kernel->handle
函数这里开始,我们才算是真正进入路由解析环节。sendRequestThroughRouter
源码如下:
在sendRequestThroughRouter
函数中主要执行三个动作。首先是调用clearResolvedInstance
函数清空已解析的请求。其次调用$this->bootstrap()
函数,执行基础应用的引导程序。最后通过Pipeline
将请求发送到中间件和路由中。最后一步比较繁琐,感谢前人的分析为我们指明捷径。直接跟入$this->dispatchToRouter()
函数。
这里调用Illuminate\Routing\Router
的dispatch
函数。也就是说将我们的请求扔进Illuminate\Routing\Router
进行处理。
接下来连续调用的三个函数都在上面的图中。逻辑也不算复杂,在函数$this->routes->match
中将传入的http请求中的uri和laravel框架加载路由解析服务时获取的路由表进行对比,若存在则返回http请求路由并继续执行$this->runRoute
方法,否则就抛出异常。在核对过路由真实有效后,便调用路由对应控制器。
在runRoute
方法中调用$this->runRouteWithinStack
。在runRouteWithinStack
方法中调用$route->run
。这里的$route
就是我们在findRoute
方法中找到的路由。跟入run
方法。
这里先是调用isControllerAction
方法判断路由处理函数是否为控制器。我们这里是false。因此直接进入$this->runCallable()
方法。到这一步基本已经接近成功了。在$this->runCallable()
方法中的resolveMethodDependencies
和parametersWithoutNulls
方法都是用来获取控制器方法的参数并且生成实例对象并注入到控制器方法中。有点像java中的依赖注入。由于我这里使用的是默认路由,控制器方法是一个匿名方法。导致下一步直接就进入匿名方法中。
小结
整体的路由解析流程就是这样。跟踪下来还是觉得laravel是一个相当成熟的框架,路由解析流程并没有明显的漏洞。laravel在路由解析这块也做了验证,保证用户只能调用已经注册的路由相对应的控制器。并且很难去绕过这一个验证。只能说在路由验证之前或者是在路由加载服务这个环节进行污染。