【问题标题】:Codeigniter redirect not preserving HTTPS in relative redirectsCodeigniter 重定向未在相对重定向中保留 HTTPS
【发布时间】:2012-01-29 06:08:11
【问题描述】:

我有一个有公共和私人区域的网站。私人区域 应通过 HTTPS 提供服务。我想重定向一次到一个显式的 HTTPS url,然后使用相对 URL,让所有链接都是安全的。当用户注销时,我将明确链接到一个绝对不安全的 HTTP URL。

我的登录表单通过常规 HTTP 显示为一个不安全的站点。我的登录表单发布到 https://www.mysite.com/login/validate ,它使用安全连接加载。

我的日志显示 Apache 正在通过 HTTPS 加载 URL,并且 codeigniter 正在正确地进行验证。

在我的控制器函数结束时,我使用 CodeIgniter 的 URL 助手的 redirect 方法和相对 URL 重定向到 /myaccount

redirect('/myaccount');

这会导致 codeigniter 重定向到非 HTTPS URL。

我的配置 base_url 是非 HTTPS:

$config['base_url'] = "http://www.mysite.com"

这是因为网站的某些部分是安全的,而其他部分则不安全。

有没有办法告诉 CodeIgniter 在进行相对重定向时保留 HTTPS?如果当前控制器是通过 HTTPS 加载的并且我正在执行相对重定向,为什么假设我想访问非 HTTPS 站点?

我想要的行为是,如果我正在执行相对重定向,它应该保留加载当前请求的协议。相反,它正在切换到配置 base_url 定义的内容,即使对于相对重定向也是如此。

【问题讨论】:

    标签: php codeigniter


    【解决方案1】:

    使用这个:

    $config['base_url'] = "http".((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on") ? "s" : "")."://".$_SERVER['HTTP_HOST'].str_replace(basename($_SERVER['SCRIPT_NAME']),"",$_SERVER['SCRIPT_NAME']);
    

    而不是这个:

    $config['base_url'] = "http://www.example.com"
    

    这将始终重定向到您想要的位置。您甚至不必输入您的域名,直接使用即可!


    除了上述之外,我还自动加载了这个助手:

    <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
    
    function is_https_on()
    {
        return isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on';
    }
    
    function use_ssl($turn_on = TRUE)
    {
        $url = $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
    
        if ( $turn_on )
        {
            if ( ! is_https_on() && $_SERVER['HTTP_HOST'] != 'localhost')
            {
                redirect('https://' . $url, 'location', 301 );
                exit;
            }
        }
        else
        {
            if ( is_https_on() )
            {
                redirect('http://' . $url, 'location', 301 );
                exit;
            }
        }
    }
    
    /* End of file https_helper.php */
    /* Location: ./application/helpers/https_helper.php */
    

    有了这个,我可以将我的各个页面设置为始终使用 HTTPS/HTTP(在我的控制器中的单个方法中,或者 - 如果我希望它影响整个控制器 - 在构造函数中)。

    我只是使用:

    use_ssl();
    

    在脚本的开头,确定它是通过 HTTPS 加载的。

    或者,如果我只想通过 HTTP 提供服务,我会使用:

    use_ssl(FALSE);
    

    【讨论】:

    • 我真的很喜欢这个答案。我遇到了同样的问题,我正在对某些助手进行扩展(如表单助手中的 form_open 和 url 助手中的 current_url )以正确检测 http 和 https 但我认为这可以处理所有事情而无需扩展几个助手。考虑到安全页面和非安全页面的受欢迎程度,不知道为什么框架中没有内置这样的东西。
    • 这很棒!我只想补充一点,一旦创建了这个帮助程序,您就可以在 config/autoload.php 文件中自动加载它。 $autoload['helper'] = array('url','html','https_helper');
    【解决方案2】:

    在 CI 中没有“开箱即用”的方式来处理这种 HTTPS/HTTP 切换。你可以做的是创建一个小助手(你自动包含),它将添加一个类似 secure_url() 的函数,并且非常简单地返回 base_url 的内容,但是 https 格式。

    您必须模拟与 secure_redirect() 相同的 redirect 函数。

    【讨论】:

    • 我喜欢这个答案,因为通过自动设置base_url redirect() 方法取决于 URL。使用其他方法,您可以根据需要执行的操作重定向到/从安全/不安全的 URL。
    【解决方案3】:

    您可以使用 相对于协议的 url,这将在 CI 中的链接中保持持久性。

    在您的config.php 中,而不是:

    $config['base_url'] = 'http://example.com/';
    

    放;

    $config['base_url'] = '//example.com/';
    

    关于协议相关链接here的信息。

    我已经使用 CI 表单库和基本链接在 ie11、chrom(e|ium)、firefox、midori 上对此进行了测试。所有浏览器都遵守规范,我已经看到它在野外使用没有问题。

    此外,CI 版本 3 还内置了 is_https 函数 你应该能够在你的控制器中简单地使用 is_https(例如在构造中)并重定向如果不是 https,然后使用上述方法维护 http 或 https 而无需不断重定向。

    例如,要将整个控制器保持为 https,请插入到您的控制器中:

    public function __construct()
    {
        parent::__construct();
        $this->load->helper('url');
        if(! is_https()){
            redirect('https:'.base_url('/page'));
        }
        //!! $conig['base_url'] must be protocol-relative
    }
    

    【讨论】:

      猜你喜欢
      • 2013-10-22
      • 1970-01-01
      • 2017-12-13
      • 1970-01-01
      • 2023-03-18
      • 2013-03-23
      • 2018-11-18
      • 2017-07-27
      • 2021-02-05
      相关资源
      最近更新 更多