I am implementing a Request
class in my MVC framework that stores all the required information from a page request.
It surely does it's job, but I was wondering if this is secure enough. I see alot of people advising against the use of $_SERVER['REQUEST_URI']
, since this can be manipulated by the end user. Have I made a good workaround, or does it still contain vulnerabilities?
class Request
{
// contains the URL of the request
private static $url = null;
// contains the request type of the request : GET | POST
private static $type = null;
// contains the segments of the request
private static $segments = null;
// contains the name of the controller of the request
private static $controller = null;
// contains the name of the method for the controller
private static $method = null;
// contains additional parameters
private static $data = null;
/*
* Prevent this class from being called 'non-statically'
*/
private function __construct() {}
/*
* Returns the Request object, so it can be used as a dependency
*/
public static function getRequest()
{
return new self;
}
/*
* Stores all Request info into the class
*/
public static function init()
{
self::$url = Sanitizer::sanitizeURL(rtrim(substr($_SERVER["REQUEST_URI"], 1), '/'));
self::$type = $_SERVER['REQUEST_METHOD'];
self::$data = (object) array();
self::parseURL();
$postParameters = filter_input_array(INPUT_POST);
$cookieParameters = filter_input_array(INPUT_COOKIE);
if(!is_null($postParameters))
{
foreach($postParameters as $parameter => $value)
{
if(!isset(self::$data->postParameters))
{
self::$data->postParameters = (object) array();
}
self::$data->postParameters->{$parameter} = $value;
}
}
if(!is_null($cookieParameters))
{
foreach($cookieParameters as $parameter => $value)
{
if(!isset(self::$data->cookieParameters))
{
self::$data->cookieParameters = (object) array();
}
self::$data->cookieParameters->{$parameter} = $value;
}
}
}
/*
* Grabs all the info from the requested URL
*/
private static function parseURL()
{
$url = self::$url;
self::$segments = explode('/', $url);
self::$data->getParameters = array_values(array_diff(array_slice(self::$segments, 2), array('')));
self::$data->controller = isset(self::$segments[0]) && !empty(self::$segments[0]) ? self::$segments[0] : 'index';
self::$data->method = isset(self::$segments[1]) && !empty(self::$segments[1]) ? self::$segments[1] : 'index';
}
/*
* Returns the requested URL
*/
public static function getURL()
{
return self::$url;
}
/*
* Returns the request type
*/
public static function getType()
{
return self::$type;
}
/*
* Returns the request data
*/
public static function getData()
{
return self::$data;
}
/*
* Returns the name of the controller
*/
public static function getController()
{
return self::$data->controller;
}
/*
* Returns the name of the method for the controller
*/
public static function getMethod()
{
return self::$data->method;
}
}
As you may have noticed, the Sanitizer
class gets called in the process. Here is what that class does:
class Sanitizer
{
private function __construct() {}
/*
* Sanitize a given URL
*/
public static function sanitizeURL($url)
{
return htmlspecialchars(strip_tags($url));
}
}
The URLs that will be requested should (if valid) look like this: {website}/profile/edit/20
.
And this is how everything gets called in my framework (note that this might be improved later on)
<?php
class Seromium
{
public static function boot()
{
require "lib/Autoloader.php";
require "lib/Config.php";
Config::init();
Autoloader::init();
Request::init();
}
}
// boot the framework
Seromium::boot();
So once again, is this code secure enough? If not, what is wrong with it and how can it be solved?
Note: Later on in my project, I will build the Router itself, which will validate if the controllers et cetera are valid and contain the given methods.
static
in this class? \$\endgroup\$