如何在Slim v3中实现Slim v2 hook作为中间件

时间:2016-02-16 11:08:01

标签: php oop slim middleware slim-3

在Slim Framework v2中,我使用简单的身份验证功能作为钩子来检查路由是否需要登录。

这是验证码:

$authenticate = function ( $app ) {
    return function () use ( $app ) {
        if ( !isset( $_SESSION['userid'] ) ) {
            $_SESSION['urlRedirect'] = $app->request()->getPathInfo();
            $app->flash('danger', 'You need to login');
            $app->redirect('/login');
        }
    };
};

这是我在Slim v2中使用的方式:

$app->get("/user/change-password", $authenticate($app), function () use ( $app ) {

 $userStuff->changePassowrd($_SESSION['userid'], $newPassword, $oldPassword);

});

我可以毫无问题地实现这个Slim v3,但我似乎无法理解我应该如何使用中间件(学习和使用功能)

我试过这个:这是我的中间件类;

<?php
namespace entity;

use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;

class Auth
{
    /**
     * Example middleware invokable class
     *
     * @param  \Psr\Http\Message\ServerRequestInterface $request  PSR7 request
     * @param  \Psr\Http\Message\ResponseInterface      $response PSR7 response
     * @param  callable                                 $next     Next middleware
     *
     * @return \Psr\Http\Message\ResponseInterface
     */
     public function __invoke($request, $response, $next)
     {
       if ($this->authenticate()) {
        $response = $next($request, $response);
      } else {
        echo 'You need to login';
      }
      return $response;
     }

     public function authenticate() {
       if ( !isset( $_SESSION['userid'] ) ) {
          return true;
       }
       return false;
     }
}

?>

注册:

$app->add( new entity\Auth() );

并且我不知道如何在路线上使用它,就像我在Slim v2中所做的那样,我在路线中添加它以检查该路由是否需要身份验证?

感谢。

2 个答案:

答案 0 :(得分:1)

基本的例子是下一个

<?php

require 'vendor/autoload.php';

session_start();

class Auth {
    public function __invoke($request, $response, $next) {
        if ($this->authenticate()) {
            $response = $next($request, $response);
        } else {
            echo 'You need to login';
        }
        return $response;
    }

    public function authenticate() {
        if (isset($_SESSION['userid'])) {
            return true;
        }
        return false;
    }
}

$app = new \Slim\App();

$app->get('/open', function($request, $response, $args){
    echo 'HAPPINESS FOR EVERYBODY, FREE, AND LET NO ONE BE LEFT BEHIND!';
});

$app->get('/closed', function($request, $response, $args){
    echo 'You are authenticated!';
})->add(new Auth());

$app->get('/login', function($request, $response, $args){
    $_SESSION['userid'] = 1;
});

$app->run();

我认为authenticate函数存在错误,因为!isset表示没有$_SESSION['userid'],可能用户未登录且您的函数告诉他已登录。

但无论如何,您可以使用add()方法将中间件添加到单个路由或一组路由中。

答案 1 :(得分:1)

您正在寻找的是实际排除Auth中间件的路由。 您确实想要检查所有其他路线,但不检查changePassword

在您的__invoke中,您需要get the current route,如果路线不是authenticate,则只能changePassword(如果这是路线的名称)。

public function __invoke($request, $response, $next)
{
    $route = $request->getAttribute('route');
    if (in_array($route->getName(), ['changePassword']) || $this->authenticate()) {
        $response = $next($request, $response);
    } else {
        echo 'You need to login';
    }
    return $response;
}