Slim的两个redirect()方法

April 3, 2013

今天我发现,我弄的登陆检验有些可以被跳过。

我用一个Route Middleware做检验,大概就这样:

<?php

function AreYouMga () {
    $app = \Slim\Slim::getInstance();

    if ( $app->getEncryptedCookie("who_are_you") !== "mga") {
        $app->response()->redirect('/login', 303);
    }
}

就是看看加密的Cookies里是不是“mga”,不是就跳转到登陆页面。

这是看起来能正常工作(实际有问题)的一例:

<?php
$app->get('/posts', 'AreYouMga', function() use ($app, $db) {

    $posts = $db->getAllPosts();
    $app->render('posts.php', array('posts' => $posts));
});

如果不是我(mga)访问 /posts就会重定向到/login

下面这个就不行了:

<?php
$app->get('/reset', 'AreYouMga', function () use ($app, $db) {
        $db->reset();
        $app->response()->redirect('/', 303);
});

不管有没有登陆,访问/reset都可以清空我的数据库然后重定向。就是因为这里的重定向有差别,我才发现这个问题。上面第一例的闭包里没有重定向所以看起来正常,实际上还是执行了。

难道是cookies设错了?还是说Slim的Route Middleware不能实现短路,闭包一定会被执行?不会是Bug吧?…

折腾一番之后,我看文档才发现有两个redirect()方法,一个是Slim对象的,一个是Response对象的。 Slim对象的redirect()设置HTTP Header然后通过抛异常实现短路,而Response对象只是设置一下HTTP Header。

所以把重定向那句换成

$app->redirect('/login', 303);

就OK了。

嗯,就样了。