CodeIgniter会话设置cookie重复--如何解决


CodeIgniter session set-cookie duplicated -- how to solve

更新:

我想知道是否有人可以查看我的答案,看看里面是否有漏洞。

在以下位置使用编解码器和会话时,存在一个有据可查的问题:

重复的";设置cookie:ci会话";编码点火器在标题中的字段

总之,每次调用set_userdata时,codeigniter都会执行一个setcookie。

我在找到了部分解决方案

http://ha17.com/1745-bigip-f5-header-max-size-collides-with-codeigniters-bizarre-session-class/

此解决方案的唯一问题是需要在所有位置插入代码。有没有一种简单的方法可以清除所有标题?我对代码进行了一些修改以删除php错误,但有没有办法使用钩子之类的东西?

<?php
class MY_Controller extends CI_Controller
{
    public function __construct()
    {
        parent:: __construct();
    }
     //See (modified from) http://ha17.com/1745-bigip-f5-header-max-size-collides-with-codeigniters-bizarre-session-class/
    protected function _removeDuplicateCookieHeaders ()
    {
        // clean up all the cookies that are set...
        $headers             = headers_list();
        $cookies_to_output   = array ();
        $header_session_cookie = '';
        $session_cookie_name = $this->config->item('sess_cookie_name');
        foreach ($headers as $header)
        {
            list ($header_type, $data) = explode (':', $header, 2);
            $header_type = trim ($header_type);
            $data        = trim ($data);
            if (strtolower ($header_type) == 'set-cookie')
            {
                header_remove ('Set-Cookie'); 
                $cookie_value = current(explode (';', $data));
                list ($key, $val) = explode ('=', $cookie_value);
                $key = trim ($key);
                if ($key == $session_cookie_name)
                {
                   // OVERWRITE IT (yes! do it!)
                   $header_session_cookie = $data;
                   continue;
                } 
                    else 
                    {
                   // Not a session related cookie, add it as normal. Might be a CSRF or some other cookie we are setting
                   $cookies_to_output[] = array ('header_type' => $header_type, 'data' => $data);
                }
            }
        }
        if ( ! empty ($header_session_cookie))
        {
            $cookies_to_output[] = array ('header_type' => 'Set-Cookie', 'data' => $header_session_cookie);
        }
        foreach ($cookies_to_output as $cookie)
        {
            header ("{$cookie['header_type']}: {$cookie['data']}", false);
        }
     }
}

EDIT:只有在使用$this->load->view()时才使用此代码。如果您在控制器中使用echo-right,这将在删除标头之前导致输出,甚至可能被删除。

EDIT需要php 5.3或更新版本。

我找到了一种方法,我认为我可以在这个问题上帮助别人。我还没有完全测试过,但它似乎有效。

application/hooks/session_cookie_fixer.php

<?php
class SessionCookieFixer
{   
     //See (modified from) http://ha17.com/1745-bigip-f5-header-max-size-collides-with-codeigniters-bizarre-session-class/
    function removeDuplicateSessionCookieHeaders ()
    {
         $CI = &get_instance();
        // clean up all the cookies that are set...
        $headers             = headers_list();
        $cookies_to_output   = array ();
        $header_session_cookie = '';
        $session_cookie_name = $CI->config->item('sess_cookie_name');
        foreach ($headers as $header)
        {
            list ($header_type, $data) = explode (':', $header, 2);
            $header_type = trim ($header_type);
            $data        = trim ($data);
            if (strtolower ($header_type) == 'set-cookie')
            {
                header_remove ('Set-Cookie'); 
                $cookie_value = current(explode (';', $data));
                list ($key, $val) = explode ('=', $cookie_value);
                $key = trim ($key);
                if ($key == $session_cookie_name)
                {
                   // OVERWRITE IT (yes! do it!)
                   $header_session_cookie = $data;
                   continue;
                } 
                    else 
                    {
                   // Not a session related cookie, add it as normal. Might be a CSRF or some other cookie we are setting
                   $cookies_to_output[] = array ('header_type' => $header_type, 'data' => $data);
                }
            }
        }
        if ( ! empty ($header_session_cookie))
        {
            $cookies_to_output[] = array ('header_type' => 'Set-Cookie', 'data' => $header_session_cookie);
        }
        foreach ($cookies_to_output as $cookie)
        {
            header ("{$cookie['header_type']}: {$cookie['data']}", false);
        }
     }
}
?>

application/config/hooks.php

$hook['post_controller'][] = array(
                               'class'    => 'SessionCookieFixer',
                               'function' => 'removeDuplicateSessionCookieHeaders',
                               'filename' => 'session_cookie_fixer.php',
                               'filepath' => 'hooks',
                               'params'   => array()
                               );

如果我正确理解您的代码,您正计划让所有控制器扩展MY_Controller,然后在每个(或可能只有相关的)控制器中,您将调用

$this->_removeDuplicateCookieHeaders()

其他替代品

添加挂钩(http://ellislab.com/codeigniter/user-guide/general/hooks.html)

$hook['post_controller_constructor'][] = array(
                            'class'    => '',
                            'function' => 'removeDuplicateCookies',
                            'filename' => 'removeDuplicateCookies.php',
                            'filepath' => 'hooks',
                            );

或创建一个助手(或库,取决于您的偏好),您可以通过编辑application/config/autoload.php

自动加载这些