如何正确结束用户会话? [英] How to properly end a users session?

查看:288
本文介绍了如何正确结束用户会话?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在研究网站(PHP)的安全性,需要吸收大量信息。我已经尝试实现在 OWASP 上研究过的安全性,但是我要做的一件事是除了其他方面,我还有些担心的是用户注销时如何处理会话。

I've been working on the security of my site (PHP) and there's a ton of information to ingest. I've tried to implement security I've researched on OWASP, but one thing I'm a little nervous about, among other things, is how to handle SESSIONS when the user logs out.

当前我正在使用的是:

session_destroy();

但是,我读到我应该更改XRSF令牌并启动另一个SESSION,以便强制执行用户重新提交登录凭据,从而明确结束用户会话。

But, I've read that I should change the XRSF token and start another SESSION so it forces the user to resubmit login credentials in-turn explicitly ending the users SESSION.

session_destroy()是否足够?

编辑

我已经下载了 michael-the-messenger ,我相信它是由Michael Brooks(Rook)创建的,应该非常安全,我看到了我可能想使用的一些代码。这可以安全地替换我正在使用的 session_destroy()吗?

I've downloaded michael-the-messenger, which I believe was created by Michael Brooks (Rook) which should be VERY secure, and I saw some code that I might want to use. Is this something that could safely replace the session_destroy() I'm using?

代码

if($_SESSION['user']->isAuth())
{
    /* if they have clicked log out */
    /* this will kill the session */
    if($_POST['LogMeOut'] == 'true')
    {
        //When the user logs out the xsrf token changes.
        $tmp_xsrf = $_SESSION['user']->getXsrfToken();
        $_SESSION['user']->logout();
        $loginMessage = str_replace($tmp_xsrf, $_SESSION['user']->getXsrfToken(), $loginMessage);
        print layout('Authorization Required', $loginMessage);
    }
    else
    {
        header("Location: inbox.php");
        //user is allowed access. 
    }
}
else
{
    // code goes on ....

注销

public function logout()
{
    $_SESSION['user'] = new auth();
}

很明显 $ _ SESSION ['user'] =新auth(); 重新实例化将私有变量 $ auth 设置为false的对象。

Obviously $_SESSION['user'] = new auth(); reinstantiates the object which sets a private variable $auth to false.

推荐答案


但我有点担心的一件事是,当用户注销时
如何处理会话。 / p>

but one thing I'm a little nervous about, among other things, is how to handle SESSIONS when the user logs out.

根据手册


为了完全终止会话,就像注销用户一样,还必须取消设置
会话ID。如果使用cookie传播
会话ID(默认行为),则必须删除
会话cookie。 setcookie()可能用于此目的。

In order to kill the session altogether, like to log the user out, the session id must also be unset. If a cookie is used to propagate the session id (default behavior), then the session cookie must be deleted. setcookie() may be used for that.

因此,为了安全地破坏会话,我们还将在客户端计算机。

So, in order to safely destroy a session, we'd also erase it on the client-machine.

session_destroy() setcookie(session_name(),null ,time()-86400)会做到这一点。

除此之外,


会话存储仅在内部使用数据序列化。通过将对象
存储在 $ _ SESSION 超全局对象中,您只需按需对
序列化/反序列化该对象,而无需了解它。

Session storage merely uses data serialization internally. By storing an object in the $_SESSION superglobal you just do serialize/unserialize that object on demand without even knowing it.

1)通过将对象存储在 $ _ SESSION 中,您确实引入了全局状态。 $ _ SESSION 是一个超全局数组,因此可以从任何地方访问。

1) By storing an object in $_SESSION you do introduce global state. $_SESSION is a superglobal array, thus can be accessed from anywhere.

2)即使通过存储一个对象保留有关已登录用户的信息,则会浪费系统内存。对象表示的长度总是大于字符串的长度。

2) Even by storing an object that keeps an information about logged user, you do waste system memory. The length of object representation is always greater than a length of the strings.

但是到底为什么您还要关心包装会话功能?好吧,

But why on earth should you even care about wrapping session functionality? Well,


  • 它使代码易于阅读,维护和测试

  • 它遵循单一责任原则

  • 它避免了全局状态(如果使用得当的话) ),则您访问会话的方式不是 $ _ SESSION ['foo'] ,而是 $ session-> read ['foo']

  • 您可以轻松更改其行为(例如,如果您决定使用数据库作为会话存储),甚至不影响应用程序的其他部分。

  • 代码重用能力。您可以将该类用于其他应用程序(或部分应用程序)

  • It makes a code easy to read, maintain and test
  • It adheres Single-Responsibility Principle
  • It avoids global state (if properly used), you'll access session not as $_SESSION['foo'], but $session->read['foo']
  • You can easily change its behaivor (say, if you decide to use DB as session storage) without even affecting another parts of your application.
  • Code reuse-ability. You can use this class for another applications (or parts of it)

如果将所有与会话相关的功能包装到signle类中,然后它将变成具有吸引力的

If you wrap all session-related functionality into a signle class, then it will turn into attractive:

$session = new SessionStorage();

$session->write( array('foo' => 'bar') );

if ( $session->isValid() === TRUE ) {

    echo $session->read('foo'); // bar

} else {

    // Session hijack. Handle here
}

// To totally destroy a session:
$session->destroy();


// if some part of your application requires a session, then just inject an instance of `SessionStorage`
// like this:
$user = new Profile($session);


// Take this implementation as example:

final class SessionStorage
{
    public function __construct()
    {
        // Don't start again if session is started:
        if ( session_id() != '' ) {
            session_start();
        }

        // Keep initial values
        $_SESSION['HTTP_USER_AGENT'] = $_SERVER['HTTP_USER_AGENT'];
        $_SESSION['REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR'];
    }

    /**
     * You can prevent majority of hijacks using this method
     * 
     * @return boolean TRUE if session is valid
     */
    public function isValid()
    {
        return $_SESSION['HTTP_USER_AGENT'] === $_SERVER['HTTP_USER_AGENT'] && $_SESSION['REMOTE_ADDR'] === $_SERVER['REMOTE_ADDR'] ;
    }


    public function __destruct()
    {
        session_write_close();
    }

    /**
     * Fixed session_destroy()
     * 
     * @return boolean
     */
    public function destroy()
    {
        // Erase the session name on client side
        setcookie(session_name(), null, time() - 86400);

        // Erase on the server
        return session_destroy();
    }


    public function write(array $data)
    {
        foreach($data as $key => $value) {
            $_SESSION[$key] = $value;
        }
    }


    public function exists()
    {
        foreach(func_get_args() as $arg){

            if ( ! array_key_exists($arg, $_SESSION) ){
                return false;
            }
        }

        return true;
    }

    public function read($key)
    {
        if ( $this->exists($key) ){

            return $_SESSION[$key];

        } else {

            throw new RuntimeException('Cannot access non-existing var ' .$key);
        }
    }

}

这篇关于如何正确结束用户会话?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆