zend-http
zend-http copied to clipboard
Https request validation
Hi ZF team! Just a little thing:
How can I check if the request
scheme is https
?
Regardless the getScheme()
method, does the Request
class has a method for that?
I can get the scheme:
$request = $this->request->getUri();
return ($request->getScheme() === 'https');
So, where should I add this validation for make it available for all controllers?
Anyways, would be great add this method on the Request
object.
$this->request->isSecure()
// or maybe
$this->request->isHttps()
Thanks! great project :1st_place_medal:
What's wrong with strtolower($uri->getScheme()) === 'https'
? Also, note that the URI does not involve "secure", as the certificate validation may have been disabled on the HTTP client.
Cool, nothing wrong with that validation, just I need to know where can I put the function and make it available for all controllers! Thanks
@diemax if you are using zend-mvc
, then a tiny injectable service would be best, but it's also simpler to enforce https
via routing and the Scheme
route
Or just create an own controller plugin.
More informations can be found in the zend-mvc
documentation.
https://docs.zendframework.com/zend-mvc/plugins/
There is no proper documentation, but you can add controller plugins to your configuration by using the controller_plugins
identifier, which is a configuration namespace for the ControllerPluginManager
.
return [
'controller_plugins' => [
'factories' => [
MyPlugin::class => InvokableFactory::class,
],
'aliases' => [
'isSecureRequest' => MyPlugin::class,
],
],
];
With that, you can execute $this->isSecureRequest()
in any Controller.
If you dont want to have such overhead, you can just create a trait and use it in your controllers:
class FooController extends AbstractActionController
{
use SecureRequestTrait;
public function indexAction()
{
if ($this->isSecureRequest($this->getRequest())) {
// Whatever
}
}
}
trait SecureRequestTrait
{
protected function isSecureRequest(RequestInterface $request)
{
if (!$request instanceof \Zend\Http\Request) {
return false;
}
return strtolower($request->getUri()->getScheme()) === 'https';
}
}
Thanks for the explanation! 😄
If you terminate HTTPS at your load balancer or gateway then requests come in to the web server with an http:// uri and the x-forwarded-proto header set to 'https'. In this case, zend frameworks getScheme functions all return 'http' when they should actually be returning 'https'.
With the current behavior, if you terminate ssl at your LB or gateway, you can't use any of the zend uri functions to generate urls that show up in your response. For example, when a user hits a page that requires authentication in our app, they are redirected to the login page and a return url is passed to the login page. Users are being redirected from an https:// page to the https:// login correctly because that is hard-coded but the return URL is being set as http:// which is a security downgrade.
This is due to $request->getUri() returning an http:// uri even if the x-forwarded-proto header is set.
I'm having trouble figuring out the best place to resolve this. I feel like the cleanest way would be to create an HttpUri class in zend-http that extends the http class from zend-uri and overrides the getScheme function to respect the x-forwarded-proto header but that class has no knowledge of the request headers.
This repository has been closed and moved to laminas/laminas-http; a new issue has been opened at https://github.com/laminas/laminas-http/issues/6.