-2

我确实知道如何使用会话/cookie。我确实为登录的用户保留会话和 cookie + 令牌。

我正在使用 MVC 结构(我自己的)并且我有一个 Login.php 控制器。我也有 User.php 类,它是一个只有 1 个实例的单例类。

我的基本控制器获取 User 的实例并存储在如下变量中:

   abstract class Controller {
    private $model;
    private $user;

    function __construct($model = '') {
        ..... //some code

        $this->user = User::getInstance();
    }

    public function user() {
        return $this->user;
    }
   }

在我的 login.php 中,一旦用户使用用户名提交表单并通过,我就有以下内容:

function logUserIn() {
    if (! isset($_POST['UName']) || ! isset($_POST['UPass'])) {
        $this->_404();
    }

    $uname = strtolower($_POST['UName']);
    $pass = Hash::strongHashMD5($_POST['UPass']);
    $token = $_POST['token'];
    $isValid = $this->model->userCheck($uname, $pass);

    $res = $this->validateUser($isValid, $token, $uname);

    if ($res === false) {
        echo 'User Does Not Exist!';
    } else if ($res === 'Token_Error') {
        echo 'Invalid Form Submission';
    } else if ($res === true) {
        //update token
        $this->model->updateToken($isValid['ID'], $token, $_SERVER['REMOTE_ADDR']);
        header("Location: ../login");   
    }
    exit;
}

这是我验证用户的方法

private function validateUser($UInfo, $token, $UName) {
    if ($UInfo !== false && isset($UInfo['ID']) && $UInfo['ID'] > 0) {
        if ($UInfo['token'] == $token) {
            return 'Token_Error';
        } else {
            $this->user()->setValues($UInfo['ID'], $UName, $token);
            $this->user()->setSessions();
            return true;
        }
    }

    return false;
}

setsessions() 方法只是设置该用户的会话/cookies

现在每次我想访问以查看用户是否登录时,我都必须通过控制器进行操作并将其传递给其他任何地方。

有没有更好的方法来做到这一点?我的代码在安全问题等方面是否有任何问题......

任何建议/建议将不胜感激,谢谢大家

4

1 回答 1

0

目前,您的领域业务逻辑到处泄漏。它应该留在模型层(是的,在正确的 MVC 中,模型是一个层而不是类或对象),而不是在表示层中。

另外,请停止使用 MD5 散列密码。如果这样做,您不妨将它们保留为纯文本。相反,您应该使用crypt()withCRYPT_BLOWFISH 或 PBKDF2 算法。

哦 .. 将人们重定向到 404,如果其中一个表单字段为空,似乎有点反应过度。

反正 ..


主题:

用户身份验证应该完全发生在模型层(更准确地说:在某些Recognition服务中)。控制器应该只向模型层提供数据,并通知当前POST已发送请求的视图。

服务在接收到数据后,应该为和分配值创建域对象。User如果数据通过验证(这是域对象的职责之一),则服务应实例化适当的数据映射器并从存储(可能是也可能不是 SQL 数据库)中获取数据。如果考虑到任何问题(例如存储中缺少记录),域对象应该符合凭据。

如果其中任何一个在某个时候失败,服务应该对错误状态采取行动并将其放入临时存储(最有可能 - 会话)。

当应用程序到达视图应该生成响应的部分时,视图实例将POST通过检查模型层中的错误状态来对有关请求的指示做出反应,并通过发送 HTTP 标头作为唯一的响应来执行重定向,具体取决于是否出现错误。

于 2012-09-13T01:27:29.807 回答