I've seen many tutorials online that says you need to check $_SERVER['HTTPS']
if the server is connection is secured with HTTPS. My problem is that on some of the servers I use, $_SERVER['HTTPS']
is an undefined variable that results in an error. Is there another variable I can check that should always be defined?
Just to be clear, I am currently using this code to resolve if it is an HTTPS connection:
if(isset($_SERVER['HTTPS'])) {
if ($_SERVER['HTTPS'] == "on") {
$secure_connection = true;
}
}
This should always work even when $_SERVER['HTTPS']
is undefined:
function isSecure() {
return
(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
|| $_SERVER['SERVER_PORT'] == 443;
}
The code is compatible with IIS.
From the PHP.net documentation and user comments :
Set to a non-empty value if the script was queried through the HTTPS protocol.
Note that when using ISAPI with IIS, the value will be "off" if the request was not made through the HTTPS protocol. (Same behaviour has been reported for IIS7 running PHP as a Fast-CGI application).
Also, Apache 1.x servers (and broken installations) might not have $_SERVER['HTTPS']
defined even if connecting securely. Although not guaranteed, connections on port 443 are, by convention, likely using secure sockets, hence the additional port check.
If there is a load balancer between the client and your server, the above code doesn't test the connection between the client and the load balancer, but the connection between the load balancer and your server. To test the connection between the client and the load balancer, you would need to check the HTTP_X_FORWARDED_PROTO
header. However, implementing this can be more complex; see latest comments below this answer.
Request
ClassSymfony provides a more robust way to determine whether the request is secure by using the Request
class from its HttpFoundation
component. This method accounts for headers set by proxies and load balancers, making it more reliable across different environments.
First, install the necessary package using Composer:
composer require symfony/http-foundation
$request->isSecure()
Then, use the Request
class:
use Symfony\Component\HttpFoundation\Request;
$request = Request::createFromGlobals();
$isSecure = $request->isSecure();
This method first checks if the request is from a recognized proxy. If it is, it considers X-Forwarded-Proto
. If the request is not from a recognized proxy, it considers $_SERVER['HTTPS']
.
If your application is behind a proxy or load balancer, you must explicitly set trusted proxies to ensure Symfony correctly interprets forwarded headers:
Request::setTrustedProxies(
['127.0.0.1', '192.168.1.1'], // Replace with actual proxy IPs
Request::HEADER_X_FORWARDED_ALL
);
Request::HEADER_X_FORWARDED_ALL
is a Symfony constant that includes all relevant forwarded headers, such as X-Forwarded-For
(client IP), X-Forwarded-Proto
(HTTPS detection), and others. This simplifies proxy handling by ensuring all forwarded headers are considered.
Alternatively, in a Symfony project, you can configure this in config/packages/framework.yaml
:
framework:
trusted_proxies: ['127.0.0.1', '192.168.1.1']
trusted_headers: ['x-forwarded-for', 'x-forwarded-proto']
In YAML configuration, trusted headers are explicitly listed. x-forwarded-for
allows Symfony to correctly determine the client IP when behind a proxy, while x-forwarded-proto
ensures proper HTTPS detection. This gives fine-grained control over which headers are trusted.
Be aware that HTTP_X_FORWARDED_PROTO
can be spoofed unless properly controlled. Always ensure that trusted proxy configurations are correctly set to avoid false HTTPS detections.