Slim PHP:只捕获带有中间件的有效路由

use*_*863 7 php slim

我正在用Slim编写REST API.我编写了一个小型中间件来保护资源,因此只有经过身份验证的用户才能访问它们:

<?php
class SecurityMiddleware extends \Slim\Middleware
{
    protected $resource;
    public function __construct($resource)
    {
        $this->resource = $resource;
    }
    public function call()
    {
        //get a reference to application
        $app = $this->app;
        //skip routes that are exceptionally allowed without an access token:
        $publicRoutes = ["/","/login","/about"];
        if (in_array($app->request()->getPathInfo(),publicRoutes)){
            $this->next->call(); //let go
        } else {
            //Validate:
            if ($this->resource->isValid()){
                $this->next->call(); //validation passed, let go
            } else {
                $app->response->setStatus('403'); //validation failed
                $app->response->body(json_encode(array("Error"=>"Access token problem")));
                return;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,但不希望的副作用是中间件不区分现有路由和不存在的路由.例如,如果用户尝试请求/dfghdfgh不存在的路由,而不是获得404的HTTP状态代码,则他将得到403表示没有访问令牌.我想在中间件类上添加类似于以下检查的实现:

if ($app->hasRoute($app->request->getPathInfo()){
    $this->next->call(); //let go so user gets 404 from the app.
}
Run Code Online (Sandbox Code Playgroud)

任何想法如何实现这一目标?

Jer*_*all 5

正如MamaWalter建议的那样,我使用一个钩子来做你正在尝试做的事情,但是你想使用slim.before.dispatch而不是早期的钩子.如果用户尝试访问的路由不存在,则永远不会调用该挂钩并404抛出该指针.

我在我自己的授权中间件中正是这样做的.奇迹般有效.


Mam*_*ter 2

不完全是你所要求的,但就个人而言,当我需要检查某些路线上的身份验证时,我会这样做。

配置:

$config = array(
    ...,

    'user.secured.urls' => array(
        array('path' => '/user'),
        array('path' => '/user/'),
        array('path' => '/user/.+'),
        array('path' => '/api/user/.+')
    ),
    ...

);
Run Code Online (Sandbox Code Playgroud)

中间件:

/**
 * Uses 'slim.before.router' to check for authentication when visitor attempts
 * to access a secured URI.   
 */
public function call()
{
    $app = $this->app;
    $req = $app->request();
    $auth = $this->auth;
    $config = $this->config;

    $checkAuth = function () use ($app, $auth, $req, $config) {

        // User restriction
        $userSecuredUrls = isset($config['user.secured.urls']) ? $config['user.secured.urls'] : array();
        foreach ($userSecuredUrls as $url) {
            $urlPattern = '@^' . $url['path'] . '$@';
            if (preg_match($urlPattern, $req->getPathInfo()) === 1 && $auth->hasIdentity() === false) {

            $errorData = array('status' => 401,'error' => 'Permission Denied');
            $app->render('error.php', $errorData, 401);
            $app->stop();                   
        }
    }

    };

    $app->hook('slim.before.router', $checkAuth);

    $this->next->call();
}
Run Code Online (Sandbox Code Playgroud)

但如果几乎所有路由都需要身份验证可能不是最好的解决方案。

很好的例子:http ://www.slideshare.net/jeremykendall/keeping-it-small-slim-php