成功登录后重定向的正确方法

时间:2012-01-28 13:02:05

标签: php redirect header signing

在调试过程中,我看到,一切顺利。出于调试目的,在

之前

header('Location:'.wsurl.'me.php');

根据生成的网址

$redirect=wsurl.'me.php';

Netbeans显示正确的网址

但是在获取此屏幕的浏览器窗口

http://img849.imageshack.us/img849/9861/c6949d6ea7ba47909d2cc37.png

并且它不会重定向到任何网址:只是保持原样。

问题

什么阻止重定向?

详细

以下是signin方法的完整代码

  public function signin() {
        if ($this->validation->check()) {
            foreach ($_POST as $k => $v)
                $$k = $v;

            $stmt = $this->db->prepare("
    SELECT u.id,    u.fname,    u.lname,    u.mname,  u.type, u.email, u.salt,
           u.pass,  u.salt,     u.approved, u.ban,      u2.status
    FROM `users` AS u
        LEFT OUTER JOIN `log` AS u2
            ON u2.user_id = u.id
    WHERE u.email = ? LIMIT 1") or die($this->db->error);

            $stmt->bind_param("s", $email) or die($stmt->error);
            $stmt->execute() or die($stmt->error);
            $stmt->store_result();
            $ip = ip2long($ip);
            if ($stmt->num_rows > 0) {
                $stmt->bind_result($id, $fname, $lname, $mname, $type, $email, $salt, $db_pass, $salt, $approved, $ban, $status) or die($stmt->error);
                $stmt->fetch() or die($stmt->error);
                $stmt->close();
                if ($status != 1) {
                    if ($approved == 1) {
                        if ($ban == 0) {
                            $hash = hash('sha256', $salt . hash('sha256', trim($pass)));
                            if ($hash == $db_pass) {
                                $token = sha1(microtime(true) . mt_rand(10000, 90000));
                                if (isset($remember) && $remember == "on") {

                                    $timeout = time() + 60 * 60 * 24 * COOKIE_TIME_OUT;

                                    $stmt = $this->db->prepare("INSERT INTO `log` (`user_id`,`ip`, `token`, `timeout`, `status`,`signin_dt`) VALUES (?,?,?,?,1,NOW())") or die($db->error);
                                    $stmt->bind_param("iiiii", $id, $ip, $token, $timeout) or die($stmt->error);
                                    setcookie('auth', "$token", $timeout);
                                } else {
                                    $stmt = $this->db->prepare("INSERT INTO `log`  (`user_id`,`ip`, `status`,`signin_dt`) VALUES (?,?,1,NOW())") or die($db->error);
                                    $stmt->bind_param("ii", $id, $ip) or die($stmt->error);
                                    session_start();
                                    session_regenerate_id(true); //this is a security measure
                                    $_SESSION['user_id'] = $id;
                                    $_SESSION['token'] = $token;
                                    $_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']);
                                    $_SESSION['remote_ip'] = $_SERVER['REMOTE_ADDR'];
                                }
                                $stmt->execute() or die($stmt->error);
                                $stmt->close();                                    
                                $redirect=wsurl.'me.php';
                                header('Location: '.$redirect); die;
                            } else {
                                die($this->ajax->respond(3));
                            }
                        } else {
                            die($this->ajax->respond(4));
                        }
                    } else {
                        die($this->ajax->respond(5));
                    }
                } else {
                    die($this->ajax->respond(6));
                }
            } else {

                die($this->ajax->respond(7));
            }
        }
    }

3 个答案:

答案 0 :(得分:2)

圣洁的鳄梨!这是一个很多的if-statements !!

很多if语句会增加Cyclomatic Complexity,这是一件非常糟糕的事情。在过去的四十年中,许多长期研究已经最终证明,具有高圈复杂性的项目实际上总是失败,因为它们太昂贵而无法维护和扩展。

请参阅http://en.wikipedia.org/wiki/Cyclomatic_complexity


如何从头开始并使用return语句和异常来控制流程呢?它会更漂亮,更容易理解,更容易[单元]测试,并且不容易出错。

这是我在自己的代码中使用的内容:

class UserController
{
    public function login()
    {
        $username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
        $password = filter_input(INPUT_POST, 'password', FILTER_SANITIZE_STRING);

        $status = $this->userManager->validatePassword($password);
        if ($status == UserManager::LOGGED_IN)
        {
            $this->createUserSession();
        }
    }
}

然后我有了这个:

class SecurityController
{
    const NOT_LOGGED_IN = 501;

    public function ensureHasAccess()
    {
        if ($this->isLoggedIn() === false)
        {
            throw new RuntimeException('User is not logged in', self::NOT_LOGGED_IN);
        }
    }
}

所以你需要做的就是确保登录用户在页面上运行的东西是这样做的:

$guard = new SecurityController;
$guard->ensureHasAccess();

那么,最后,在web / index.php中,我有这个:

try
{
    // DO web stuff here.
}
catch (RuntimeException $e)
{
    if ($e->getCode() == SecurityController::NOT_LOGGED_IN)
    {
        // Oops! The user isn't logged in... Redirect!!
        header('Location: http://' . $_SERVER['HTTP_HOST'] . '/user_directory/?errmsg=not+logged+in');
        exit; // Thanks, drrcknlsn!
    }
}

我甚至创建了一个演示应用来教人们这类东西。 PHP大学的代码仓库的一部分:http://repo.phpexperts.pro/source/user_directory/files

答案 1 :(得分:0)

如果ajax_respond()向浏览器发送输出,则无法通过header()调用来执行此操作,因为输出已经发送。 AJAX响应通常不会跟随任何重定向,因为客户端浏览器不打算重新加载页面。相反,AJAX响应在页面中处理,不会发生重定向。

答案 2 :(得分:0)

显然,如果您要重定向到wsurl . 'me.php'并且浏览器只是尝试请求me.php,那么您的问题是wsurl为空。我不知道究竟wsurl到底是什么,但如果它应该是变量,那么它应该是$wsurl而不是wsurl。如果它是常量,请确保它定义的文件包含在此文件中。无论它是什么,请确保正确拼写它,使用适当的外壳等。

但是你应该真的使用PHP错误日志。在这样的情况下,它会告诉你到底出了什么问题以及在哪里。