PHP获取站点URL协议-http与https


197

我编写了一个小函数来建立当前站点的URL协议,但是我没有SSL,也不知道如何测试它是否可以在https下工作。你能告诉我这是否正确吗?

function siteURL()
{
    $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
    $domainName = $_SERVER['HTTP_HOST'].'/';
    return $protocol.$domainName;
}
define( 'SITE_URL', siteURL() );

是否有必要像上面那样做,还是我可以像那样做?:

function siteURL()
{
    $protocol = 'http://';
    $domainName = $_SERVER['HTTP_HOST'].'/'
    return $protocol.$domainName;
}
define( 'SITE_URL', siteURL() );

在SSL下,即使定位标记网址使用的是http,服务器也不会自动将网址转换为https吗?是否需要检查协议?

谢谢!


1
对于您来说,安装本地Web服务器并在其上抛出自签名SSL证书不是更好的选择吗?这样,您就可以自己对其进行测试。
Frazell Thomas

是的,那太棒了,但是我不知道该怎么做。

4
虽然这不能回答您的问题,但是(相对于我所知,我无法确定)一个更好的解决方案可能是使用Protocol Relative URLs
里斯·摩尔

只是一个简单的问题...如果功能不是动态的,您怎么来做一个功能。就像您不给它提供任何var来更改url一样。为什么不定义一个常数?那就是我所做的。$ protocol =(!empty($ _ SERVER ['HTTPS'])&& $ _SERVER ['HTTPS']!=='off'|| $ _SERVER ['SERVER_PORT'] == 443)吗?“ https://”:“ http://”; define('SITE_URL',$ protocol。$ _ SERVER ['HTTP_HOST']。'/');
HTMLGuy 2013年

Answers:


69

这不是自动的。您的最高职能看起来还不错。


19
值得一提的是,如果您只是不遵守协议,它是自动的。即,//mysqite.com而不是https://mysitecom
我摔跤了一次。

4
@Pamblam,//效果很好,除非您的链接在电子邮件中:)
TimoSolo

或在xhr请求中
Lucas Morgan

86

我知道已经很晚了,尽管有解决此问题的便捷方法!其他解决方案非常混乱。这就是我会做的:

$protocol = stripos($_SERVER['SERVER_PROTOCOL'],'https') === 0 ? 'https://' : 'http://';

...或者甚至无条件,如果您愿意:

$protocol = strtolower(substr($_SERVER["SERVER_PROTOCOL"],0,strpos( $_SERVER["SERVER_PROTOCOL"],'/'))).'://';

看一下 $_SERVER["SERVER_PROTOCOL"]


20
以“https”这不工作stackoverflow.com/questions/16825243/...
wormhit

@wormhit它主要取决于您的网络服务器的配置方式
Ivo

您为什么使用stripos而不是strpos
Fred

12
$_SERVER['SERVER_PROTOCOL']是用于存储HTTP/1.0还是HTTP/1.1取决于协议版本,您谈论什么类型的HTTP服务器配置,用于存储https来自http查询的有关此字符串的信息?
regilero'2

1
在我的情况下不起作用!协议为https时,$ _ SERVER ['SERVER_PROTOCOL']包含“ HTTP”(不带任何“ S”)。检查$ _SERVER ['HTTPS']更合适。
西蒙嗨

68

这对我有用

if (isset($_SERVER['HTTPS']) &&
    ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) ||
    isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
    $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
  $protocol = 'https://';
}
else {
  $protocol = 'http://';
}

3
如果使用代理(例如我的案例CloudFlare),这是可行的解决方案
Jess Carrera

1
这是正确的-你不应该假设HTTPS只是因为你正在使用端口443
马克·费舍尔

24

一些变化:

function siteURL() {
  $protocol = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || 
    $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
  $domainName = $_SERVER['HTTP_HOST'];
  return $protocol.$domainName;
}

16

短路

$scheme = $_SERVER['REQUEST_SCHEME'] . '://';

3
REQUEST_SCHEME不可靠
Farnabaz

5
REQUEST_SCHEME在Apache 2.4之前不可用。
KenB

7

因为根据我的看法,测试端口号不是一个好习惯,所以我的解决方案是:

define('HTTPS', isset($_SERVER['HTTPS']) && filter_var($_SERVER['HTTPS'], FILTER_VALIDATE_BOOLEAN));

HTTPS报酬不变TRUE,如果$_SERVER['HTTPS']设置和“on”或“是”等于“1”,“真实的”。否则返回FALSE。


这可能是最好的答案。这些答案很多只会在一定比例的情况下出现。例如,人们只是在检查是否设置了$ _SERVER ['HTTPS']。许多框架将此变量设置为false或“ off”等,因此,检查是否简单设置该变量将不起作用。
丹尼尔·德赫斯特

1
尽管在大多数情况下都可以使用此功能,但有时会存在SNAFU的配置,并且$ _SERVER ['HTTPS']实际上设置为“ off”。您的代码仍将其视为“通过”测试,因此应进行修改以允许该特定设置。
戴夫·莫顿


5

如果使用代理,则SERVER_PORT可能无法提供正确的值,因此这对我有用-

$protocol = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || $_SERVER['SERVER_PORT'] == 443 || $_SERVER['HTTP_X_FORWARDED_PORT'] == 443) ? "https://" : "http://"

4

使用此服务器变量来获取协议详细信息:

 $scheme = $_SERVER['REQUEST_SCHEME'] . '://';
 echo $scheme; //it gives http:// or https://

请注意,此服务器变量不可靠。有关更多信息,请查看: $ _SERVER ['REQUEST_SCHEME']可靠吗?


您可以在帖子中添加更多信息,而不仅仅是代码吗?例如解释为什么这是问题的答案?
ndsmyter

3

我知道这是一个老问题,但是由于我需要在自己的网站中对此进行测试,因此我今天遇到了这个问题。似乎以上答案不必要地复杂。要建立站点协议,您要做的就是测试$_SERVER['HTTPS']

如果协议使用HTTPS,$_SERVER['HTTPS']则将返回“ on”。如果不是,变量将保持为空。例如:
// test if HTTPS is being used. If it is, the echo will return '$SSL_test: on'. If not HTTPS, '$SSL_test' will remain empty.

$SSL_test = $_SERVER['HTTPS'];

echo '<p>$SSL_test: '.$SSL_test.'</p>';

if($SSL_test == true) {
    echo 'You\'re using SSL';
} else {
    echo 'You\'re not using SSL';
} 

您可以使用上面的代码轻松干净地测试HTTPS并相应地实施。:)


2
并非每个服务器都有此$ _SERVER ['HTTPS']
ChrisDeDavidMindflowAU

2

使用Rid Iculous的答案创建了一个函数,该函数在我的系统上有效。

function site_protocol() {
    if(isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) &&  $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')  return $protocol = 'https://'; else return $protocol = 'http://';
}

希望能帮助到你


2

我测试了投票率最高的答案,但该方法对我不起作用,最终我使用了:

$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';

某些Web服务器不支持$_SERVER["HTTPS"],因此您的代码http://即使应返回也可能返回https://
nathanfranke

如果服务器不支持,https为什么代码仍然返回https
CONvid19

我的服务器支持https,但是$_SERVER["HTTPS"]从未定义变量。
nathanfranke

您的2条评论让我感到困惑。如果创建一个涵盖这些特殊情况的新答案可能会更好。谢谢,祝你好运!
CONvid19


2

从CodeIgniter中提取:

if ( ! function_exists('is_https'))
{
    /**
     * Is HTTPS?
     *
     * Determines if the application is accessed via an encrypted
     * (HTTPS) connection.
     *
     * @return  bool
     */
    function is_https()
    {
        if ( ! empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off')
        {
            return TRUE;
        }
        elseif (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https')
        {
            return TRUE;
        }
        elseif ( ! empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off')
        {
            return TRUE;
        }

        return FALSE;
    }
}

0

这是https或http的最佳解决方案,请使用以下命令:

<?php
$protocol = '//';  
$site_url = $protocol.$_SERVER["HTTP_HOST"];
?>

但是无法显示https或http,因此它仅用于链接您的网站内容(例如图片等)。

如果要在https中重定向您的网站,请在.htaccess文件中添加以下代码:

<IfModule mod_rewrite.c>
 RewriteCond %{HTTP:CF-Visitor} '"scheme":"http"'
 RewriteRule ^(.*)$ https://www.your-domain.com$1 [L]
</IfModule>

用您的域名来更改www.your-domain.com


0

下面是我如何做到这一点?这是一个速记 if else的版本摆脱Iculous的答案...

$protocol = isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] === 'on' || $_SERVER['HTTPS'] === 1) || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' ? 'https' : 'http';

0

我认为完整的功能应该如下所示:

function siteURL()
{
    $protocol =  "http://";
    if (
        //straight
        isset($_SERVER['HTTPS']) && in_array($_SERVER['HTTPS'], ['on', 1])
        ||
        //proxy forwarding
        isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https'
    ) {
        $protocol = 'https://';
    }

    $domainName = $_SERVER['HTTP_HOST'];
    return $protocol . $domainName;
}

笔记:

  • 您还应该查找HTTP_X_FORWARDED_PROTO(例如,如果代理服务器)
  • 依赖443端口是不安全的(可以在其他端口上使用https)
  • REQUEST_SCHEME不可靠

0

我知道我参加这个聚会有点晚了,但是如果您不愿意使用$ _SERVER,因为它强烈建议不要使用它,甚至在某些PHP框架上将其停用,则可以;并且您有一个apache网络服务器,因此可以使用它的本机命令:-

$protocol = apache_getenv('HTTPS') ? 'https:' : 'http:';
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.