我有一个有公共和私人区域的网站。私人区域应该通过HTTPS提供。我想重定向一次到一个明确的HTTPS url,然后,使用相对url,所有的链接是安全的。当用户登出时,我将显式链接到一个绝对不安全的HTTP URL。
我的登录表单通过常规HTTP显示一个不安全的站点。我的登录表单发布到https://www.mysite.com/login/validate
,它使用安全连接加载。
我的日志显示Apache正在通过HTTPS加载URL, codeigniter正在正确地进行验证。
在我的控制器功能结束时,我使用CodeIgniter的URL助手的redirect
方法与相对URL重定向到/myaccount
。
redirect('/myaccount');
这会导致编码器重定向到非https URL。
我的配置base_url是非https:
$config['base_url'] = "http://www.mysite.com"
这是因为网站的某些部分是安全的,而其他部分则不是。
是否有一种方法告诉CodeIgniter保存HTTPS时做相对重定向?如果当前控制器是通过HTTPS加载的,那么为什么我想去一个非HTTPS站点,而我正在做一个相对重定向?
我想要的行为是,如果我做相对重定向,它应该保留当前请求被加载的协议。相反,它会切换到配置base_url所定义的内容,甚至对于相对重定向也是如此。
使用
$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);
在CI中没有'开箱即用'的方法来处理这种HTTPS/HTTP切换。您可以做的是创建一个小的助手(您自动包含),它将添加一个功能,如secure_url()
,并相当简单地返回base_url
将,但https格式。
您将不得不模拟相同的redirect
功能,可能作为secure_redirect()
。
您可以使用协议-相对url,它将在CI中保持链接的持久性。
在config.php
中代替:
$config['base_url'] = 'http://example.com/';
把;
$config['base_url'] = '//example.com/';
协议相关链接信息。
我已经在ie11, chrome,firefox,midori上使用CI表单库和基本链接进行了测试。所有的浏览器都支持这个规范,我也看到它在野外使用时没有任何问题。
另外,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
}