1

我一直在测试新的 Slim 4 框架,并且重定向在普通类中对我来说工作正常,但我似乎无法让它们在中间件中工作,其中响应是由请求处理程序动态生成的(显然?)。当我尝试使用 Location 标头重定向时,它根本无法重定向,并且我的路线继续到原始位置。

这是我用于测试的身份验证中间件的基本版本:

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;

class AuthMiddleware extends Middleware {

    public function __invoke(Request $request, RequestHandler $handler): Response {
        $response = $handler->handle($request);
        $loggedInTest = false;
        if ($loggedInTest) {
            echo "User authorized.";
            return $response;
        } else {
            echo "User NOT authorized.";
            return $response->withHeader('Location', '/users/login')->withStatus(302);
        }
    }
}

有没有人让这个工作?如果是这样,你是如何做到的?提前致谢。

4

3 回答 3

4

我想我看到了这段代码的问题。

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;

class AuthMiddleware extends Middleware {

    public function __invoke(Request $request, RequestHandler $handler): Response {
        $response = $handler->handle($request);
        $loggedInTest = false;
        if ($loggedInTest) {
            echo "User authorized.";
            return $response;
        } else {
            echo "User NOT authorized.";
            return $response->withHeader('Location', '/users/login')->withStatus(302);
        }
    }
}

当您调用$handler->handle($request)时,它会正常处理请求并调用任何应该处理路由的闭包。响应尚未完成,您仍然可以向其附加内容,但标头已设置,因此您无法进行重定向,因为标头已完成。

也许试试这个:

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Psr7\Response;

class AuthMiddleware extends Middleware {

    public function __invoke(Request $request, RequestHandler $handler): ResponseInterface {            
        $loggedInTest = false;
        if ($loggedInTest) {
            $response = $handler->handle($request);
            echo "User authorized.";
            return $response;
        } else {
            $response = new Response();
            // echo "User NOT authorized.";
            return $response->withHeader('Location', '/users/login')->withStatus(302);
        }
    }
}

如果登录测试失败,我们永远不会调用$handler->handle(),因此不会生成正常响应。同时,我们创造了一个新的回应。

请注意,ResponseInterfaceandResponse不能Response在同一个文件中同时调用,因此我必须删除该别名,而只需ResponseInterface使用其真实名称调用。你可以给它一个不同的别名,但我认为这只会造成更多的混乱。

另外,我在重定向之前注释掉了回声。我认为这个回声会强制标头自动发送,这会破坏重定向。除非 Slim 4 正在做输出缓冲,在这种情况下你仍然看不到它,因为重定向会立即将你发送到不同的页面。无论如何,我将其注释掉以使代码有最好的工作机会,但将其保留以供参考。

无论如何,我认为如果你做出那么小的改变,一切都会奏效。当然,这篇文章已经快一年了,所以你可能已经自己解决了这个问题,切换到 F3,或者现在放弃了这个项目。但希望这对其他人有帮助。这就是 StackOverflow 的重点,对吧?

于 2020-08-07T14:15:16.940 回答
0

我对 Slim 4 和重定向问题感到越来越沮丧,以至于我查看了 FatFreeFramework 并遇到了完全相同的问题。所以我知道这是我正在做的事情。我的代码将应用程序置于永无止境的重定向循环中。我可以通过在 FatFreeFramework 中验证重定向 URL 来使其工作:

class Controller {

    protected $f3;

    public function __construct() {
        $isLoggedIn = false;
        $this->f3 = Base::instance();
        if ($isLoggedIn == false && $_SERVER['REQUEST_URI'] != '/login') {
            $this->f3->reroute('/login');
            exit();
        }
    }
}

因此,虽然我实际上并没有花时间测试它,但我假设我可以通过执行以下操作在 Slim 4 中修复它:

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;

class AuthMiddleware extends Middleware {

    public function __invoke(Request $request, RequestHandler $handler): Response {
        $response = $handler->handle($request);
        $loggedInTest = false;
        if (!$loggedInTest && $_SERVER['REQUEST_URI'] != '/user/login') {
            return return $response->withHeader('Location', '/users/login')->withStatus(302);
        } else {
            return $response;
        }
    }
}

有人对如何打破连续重定向循环有其他想法吗?还是 $_SERVER 变量是最好的选择?

提前致谢。

于 2019-10-18T06:14:48.267 回答
0

eimajen是对的,只是你不能创建接口的实例。

试试这个:

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Psr7\Response;

class AuthMiddleware extends Middleware {

public function __invoke(Request $request, RequestHandler $handler): Response {            
    global $app; // Assuming $app is your global object

    $loggedInTest = false;
    if ($loggedInTest) {
        $response = $handler->handle($request);
        echo "User authorized.";
        return $response;
    } else {
        $response = $app->getResponseFactory()->createResponse();
        // echo "User NOT authorized.";
        return $response->withHeader('Location', '/users/login')->withStatus(302);
    }
}

}

于 2020-12-25T17:57:38.720 回答