im re-factoring php on zend code and all the code is full of $_GET["this"] and $_POST["that"]. I have always used the more phpish $this->_request->getPost('this') and $this->_request->getQuery('that') (this one being not so much logical with the getquery insteado of getGet).
So i was wondering if my method was safer/better/easier to mantain. I read in the Zend Framework documentation that you must validate your own input since the request object wont do it.
That leaves me with 2 questions:
What is best of this two? (or if theres another better way)
What is the best practice for validating php input with this methods?
Thanks!
I usually use $this->_request->getParams(); to retrieve either the post or the URL parameters. Then I use the Zend_Filter_Input to do validation and filtering. The getParams() does not do validation.
Using the Zend_Filter_Input you can do application level validation, using the Zend Validators (or you can write your own too). For example, you can make sure the 'months' field is a number:
$data = $this->_request->getParams();
$validators = array(
'month' => 'Digits',
);
$input = new Zend_Filter_Input($filters, $validators, $data);
Extending Brian's answer.
As you noted you can also check out $this->_request->getPost() and $this->_request->getQuery(). If you generalize on getParams(), it's sort of like using the $_REQUEST superglobal and I don't think that's acceptable in terms of security.
Additional to Zend_Filter, you may also use simple PHP to cast the required.
E.g.:
$id = (int) $this->_request->getQuery('id');
For other values, it gets more complicated, so make sure to e.g. quote in your DB queries (Zend_Db, see quoting identifiers, $db->quoteIdentifier()) and in views use $this->escape($var); to escape content.
You can't write a one-size-fits-all validation function for get/post data. As in some cases you require a field to be a integer and in others a date for instance. That's why there is no input validation in the zend framework.
You will have to write the validation code at the place where you need it. You can of course write some helper methods, but you can't expect the getPost() to validate something for you all by itself...
And it isn't even getPost/getQuery's place to validate anything, it's job is to get you the data you wan't, what happens to it from there on should not be it's concern.
$dataGet = $this->getRequest()->getParam('id',null);
$valid = new Zend_Validate_Digits();
if( isset($dataGet) && $valid->isValid($dataGet) ){
// do some...
} else{
// not set
}
I have always used the more phpish $this->_request->getPost('this') and $this->_request->getQuery('that') (this one being not so much logical with the getquery insteado of getGet).
What is best of this two? (or if theres another better way)
Just a quick explanation on the choice of getQuery(). The wording choice comes from what kind of data it is, not how it got there. GET and POST are just request methods, carrying all sorts of information, including, in the case of a POST request, a section known as "post data". A GET request has no such block, any variable data it carries is part of the query string of the url (the part after the ?).
So, while getPost() gets the data from the post data section of a POST request, getQuery() retrieves data from the query string of either a GET or POST request (as well as other HTTP Request methods).
(Note that GET Requests should not be used for anything that might produce a side effect, like altering a DB row)
So, in answer to your first question, use the getPost() and getQuery() methods, this way, you can be sure of where the data source (if you don't care, getParams() also works, but may include additional data).
What is the best practice for validating php input with this methods?
The best place to validate input is where you first use it. That is to say, when you pull it from getParams(), getPost(), or getQuery(). This way, your data is always correct for where you need it, and if you pass it off, you know it is safe. Keep in mind, if you pass it to another Controller (or Controller Action), you should probably check it again there, just to be safe. How you do this depends on your application, but it still needs to be checked.
not directly related to the topic, but
to insure that you get an number in your input, one could also use $var+0
(however if $var is a float it stays a float)
you may use in most cases
$id = $this->_request->getQuery('id')+0;
Related
I'm quite new to Joomla! (and PHP in general) and trying to learn by developing a website on my local Joomla!-Installation.
I'm using WAMP-Server with PHP 5.5.12, Apache 2.4.9 and Joomla! 3.6.4.
Now I like to retrieve data from both $_POST and $_GET. Both are equaly insecure so it is only logical to retrieve and treat them together.
According to this article https://docs.joomla.org/Secure_coding_guidelines#Secure_strings i should be able to do it like this:
$string = JFactory::getApplication()->input->method->getString( 'myText', '' );
It's not working, complaining that 'method' is a non-object. ('Fatal error: Call to a member function getString() on a non-object')
All other data-source's from that same list (e.g. 'get', 'post', 'cookie', 'request', etc.) do not produce any error and seem to work flawless.
Unfortunately I need to retrieve data from either $_POST or $_GET (or both, but without $_COOKIE) wich is exactly what data-source='method' is supposed to do.
Of course I can use 'post' and 'get' sequentially but that seems stupid to me if there is an option wich could do it directly (less overhead? and slimmer code).
Than I maybe have to address priority, but let's leave that aside for now.
At https://docs.joomla.org/Retrieving_request_data_using_JInput the only Super-Global-'s mentioned are 'get', 'post' and 'server'. Not a word about the other sources that obviously
exist (no error occurring) or wich of the named sources is used as default.
My search has gone in circles for a while now and i can't find more related informations (targeting Joomla! or JInput, not PHP).
If I'm missing something fundamental here, feel free to tell me.
With this said my questions are now:
Is there any setting (or update) i have to make to get the 'method'-data-source working?
Is there another value (!='method') for data-source in JInput that can be used to directly retrieve data from exactly either $_POST
or $_GET or do I need to sequentially call 'post' and 'get' to accomplish this (maybe 'method' was renamed due to a conflict in names)?
Thanks for your time reading (and maybe answering).
I finally figured it out, thx to #Xorifelse for a push in the right direction.
The answers to my questions would be:
1) Is there any setting (or update) i have to make to get the 'method'- working?
One would have to add an array called '_METHOD' to the $GLOBALS-array in a way like this:
$GLOBALS['_METHOD'] = array_merge($_GET,$_POST);
Calling the JInput with data-source='method' then would return the merged content of $_GET and $_POST, with $_POST overwriting
values in $_GET if they have the same key.
2) Is there another value (!='method') for data-source in JInput that can be used...?
Every existing array inside the $GLOBALS-array (who's name starts with an underscore ('_') character and consists of uppercase characters only) can be used by calling the JInput with data-source beeing the name of that array (without the leading underscore).
If one has newly created and/or filled that array prior to the call by JInput doesn't matter. So using a name like _GETANDPOST instead of
_METHOD in the first question would describe its purpose mutch better.
BUT....
messing around with $GLOBALS is commonly considered bad practice!!
For everyone wondering how these values for the data-source in JInput work and why they seemingly could be called like a method
even they aren't methods:
the answer is to be found in 'magic methods' and 'property overloading'.
https://secure.php.net/manual/en/language.oop5.magic.php
https://secure.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members
Is it OK to use
$id = $request->get('some_id');
instead of setting some parameters in Routes AND Controller like:
Route::get('some_page/{parameters}', 'controllerName#functionName');
function functionName($parameters)
{
$id = $parameters;
}
Appreciation
Of course it's good. When you're using GET, both ways are similar and if you like to use $request->get() for some reason, it's totally ok.
If you're using Form, it's the only right way. Plus, you can create custom Request class to use it for validation and other operations:
https://laravel.com/docs/master/validation#form-request-validation
They have two fundamentally different goals.
Using $request->get() is a way to retrieve a value from inside the php's REQUEST object regardless of its association with routing pattern you use.
Following HTTP's standards, you probably use $_GET to read some value without it changing the database [significantly] and you use $_POST to write data to you server.
While {pattern} in routing ONLY and ONLY should be used as a way for your application to locate something, some resource(s); in other words, its only goal is to help you route something in your server.
Nevertheless, in certain cases, such as /user/{id} the value of {id} might encounter some overlapping as to whether be treated as a route parameter or as a key of $_REQUEST.
Things such as tokens, filters criteria, sorting rules, referrers (when not significantly) etc. can be read right from $_REQUEST without interfering them into routing pattern of you application.
There is a sample in the bottom of the official documentation http://kohanaframework.org/3.2/guide/kohana/security/validation
But obviously it wont work at the request as long as $post['username'] in View is used but the $post array is empty on first request.
So how do you restore the values in this case? Any general solution?
PS: yes, I do understand I could do isset($post['username']) ? $post['username'] : ''; but it is just annoying
I use the model to display the data in the form. That way the initial form value is the initial value in the model.
I then update the model data with POST data in the controller, if there are validation errors, the model data will contain the POST data. This means I don't have to put any conditional logic in the view, and I just do: Form::input('name', $model->name)
Here's a more detailed explanation of this approach: Kohana ORM and Validation, having problems
I use Arr::get function:
echo Form::input('name', Arr::get($post, 'name'))
I was just looking at the old documentation on Building and Validating a Form.
You can see from the sample code that first you need to initialize an array with the form field names as the key and set the value to an empty string. And if there's an error, fill in the values of each element. In the views, you can simply call Form::input() normally without any if statement or some sort.
I guess Kohana has already been built this way from the start. And it doesn't seem to change. You'll probably just need to do the same thing.
So, I don't come from a huge PHP background—and I was wondering if in well formed code, one should use the 'superglobals' directly, e.g. in the middle of some function say $_SESSION['x'] = 'y'; or if, like I'd normally do with variables, it's better to send them as arguments that can be used from there, e.g:
class Doer {
private $sess;
public function __construct(&$sess) {
$this->sess =& $sess;
}
}
$doer = new Doer($_SESSION);
and then use the Doer->sess version from within Doer and such. (The advantage of this method is that it makes clear that Doer uses $_SESSION.)
What's the accepted PHP design approach for this problem?
I do like to wrap $_SESSION, $_POST, $_GET, and $_COOKIE into OOP structures.
I use this method to centralize code that handles sanitation and validation, all of the necessary isset () checks, nonces, setcookie parameters, etc. It also allows client code to be more readable (and gives me the illusion that it's more maintainable).
It may be difficult to enforce use of this kind of structure, especially if there are multiple coders. With $_GET, $_POST, and $_COOKIE (I believe), your initialization code can copy the data, then destroy the superglobal. Maybe a clever destructor could make this possible with $_SESSION (wipe $_SESSION on load, write it back in the destructor), though I haven't tried.
I don't usually use any of these enforcement techniques, though. After getting used to it, seeing $_SESSION in code outside the session class just looks strange, and I mostly work solo.
EDIT
Here's some sample client code, in case it helps somebody. I'm sure looking at any of the major frameworks would give you better ideas...
$post = Post::load ();
$post->numeric ('member_age');
$post->email ('member_email');
$post->match ('/regex/','member_field');
$post->required ('member_first_name','member_email');
$post->inSet ('member_status',array('unemployed','retired','part-time','full-time'));
$post->money ('member_salary');
$post->register ('member_last_name'); // no specific requirements, but we want access
if ($post->isValid())
{
// do good stuff
$firstName = $post->member_first_name;
}
else
{
// do error stuff
}
Post and its friends all derive from a base class that implements the core validation code, adding their own specific functionality like form tokens, session cookie configuration, whatever.
Internally, the class holds a collection of valid data that's extracted from $_POST as the validation methods are called, then returns them as properties using a magic __get method. Failed fields can't be accessed this way. My validation methods (except required) don't fail on empty fields, and many of them use func_get_args to allow them to operate on multiple fields at once. Some of the methods (like money) automatically translate the data into custom value types.
In the error case, I have a way to transform the data into a format that can be saved in the session and used to pre-populate the form and highlight errors after redirecting to the original form.
One way to improve on this would be to store the validation info in a Form class that's used to render the form and power client-side validation, as well as cleaning the data after submission.
Modifying the contents of the superglobals is considered poor practice. While there's nothing really wrong with it, especially if the code is 100% under your control, it can lead to unexpected side effects, especially when you consider mixed-source code. For instance, if you do something like this:
$_POST['someval'] = mysql_real_escape_string($_POST['someval']);
you might expect that everywhere PHP makes that 'someval' available would also get changed, but this is not the case. The copy in $_REQUEST['someval'] will be unchanged and still the original "unsafe" version. This could lead to an unintentional injection vulnerability if you do all your escaping on $_POST, but a later library uses $_REQUEST and assumes it's been escaped already.
As such, even if you can modify them, it's best to treat the superglobals as read-only. If you have to mess with the values, maintain your own parallel copies and do whatever wrappers/access methods required to maintain that copy.
I know this question is old but I'd like to add an answer.
mario's classes to handle the inputs is awesome.
I much prefer wrapping the superglobals in some way. It can make your code MUCH easier to read and lead to better maintainability.
For example, there is some code at my current job the I hate! The session variables are used so heavily that you can't realistically change the implementation without drastically affecting the whole site.
For example,
Let's say you created a Session class specific to your application.
class Session
{
//some nice code
}
You could write something like the following
$session = new Session();
if( $session->isLoggedIn() )
{
//do some stuff
}
As opposed to this
if( $_SESSION['logged'] == true )
{
//do some stuff
}
This seems a little trivial but it's a big deal to me. Say that sometime in the future I decide that I want to change the name of the index from 'logged' to 'loggedIn'.
I now have to go to every place in the app that the session variable is used to change this. Or, I can leave it and find someway to maintain both variables.
Or what if I want to check that that user is an admin user and is logged in? I might end up checking two different variables in the session for this. But, instead I could encapsulate it into one method and shorten my code.
This helps other programmers looking at your code because it becomes easier to read and they don't have to 'think' about it as much when they look at the code. They can go to the method and see that there is only ONE way to have a logged in user. It helps you too because if you wanted to make the 'logged' in check more complex you only have to go to one place to change it instead of trying to do global finds with your IDE and trying to change it that way.
Again, this is a trivial example but depending on how you use the session this route of using methods and classes to protect access could make your life much easier to live.
I would not recommend at all passing superglobal by reference. In your class, it's unclear that what you are modifying is a session variable. Also, keep in mind that $_SESSION is available everywhere outside your class. It's so wrong from a object oriented point of view to be able to modify a variable inside a class from outside that class by modifying a variable that is not related to the class. Having public attribute is consider to be a bad practice, this is even worst.
I found my way here while researching for my new PHP framework.
Validating input is REALLY important. But still, I do often find myself falling back to code like this:
function get( $key, $default=FALSE ){
return (isset($_GET[$key]) ? $_GET[$key]:$default);
}
function post( $key, $default=FALSE ){
return (isset($_POST[$key]) ? $_POST[$key]:$default);
}
function session( $key, $default=FALSE ){
return (isset($_SESSION[$key]) ? $_SESSION[$key]:$default);
}
Which I then use like this:
$page = get('p', 'start');
$first_name = post('first_name');
$last_name = post('last_name');
$age = post('age', -1);
I have found that since I have wildly different requirements for validation for different projects, any class to handle all cases would have to be incredibly large and complex. So instead I write validation code with vanilla PHP.
This is not good use of PHP.
get $_SESSION variables directly:
$id = $_SESSION['id'];
$hash = $_SESSION['hash'];
etc.
I have only recently started web programming and I am pretty much amazed that although I am using a validation library, I still get 20-30 lines of code for validation alone, not counting error messages and callback functions. I am using the Kohana MVC framework and I was wondering if there was any way I can shorten my validation codes. I tried to think of the following
putting validation codes in my model (which is quite had for a noob like me).
creating a really small library to validate entries(something that hooks to the validation class, thus allowing me to call the library for repetitive procedures like user registration, editing and stuff)
Or are there any better and more efficient ways?
I would highly recommend working on including the validation in the model. Once you are able to do one, any others you create will be much easier. Plus if you have multiple controllers trying to save that data, you will not need to recode the validation. The Kohana docs contain some examples for integrating the validation library and ORM, you should start there.
I use Zend_Validate with Zend_Forms for validation in which the validation code is in the forms init method. All I have to do is pass an array of validators for each element and than run ..
$form->isValid($data);
...outside of the form to validate the data.
The validation array is easily more than 30 lines because I seperate each array entry with a newline. But i guess you will have that if you defining fine grained validation rules for each element right.
And its really easy to define new Validators in Zend.
edit: i discovered a framework that extends the Zend Framework which allows domain objects to contain its own validation. Its called Xyster framework but I could not get it to work on the first try so I haven't tried after that.
Here's my strategy for dealing with validation code. I suppose by 'validation library', you mean those which just make sure an email is an email, telephone numbers are numerical, and are not business rules in nature.
The idea is to have each business rule code as a functor - if it is PHP, you can get by just using a string to define the function; for other languages, you may have to use the strategy pattern. Define an interface for the functor (not necessary for PHP) and dump it into an array.
Run through the array which will return success, error and an error-code to a buffer. At the end, examine the error buffer and determine which validation has failed. Use it to customise the view.
Here's an example
$checkUniqueUserName = new CheckUniqueUserName();
$checkEmailNotUsed = new EmailNotUsed();
$validator = array();
$validator[$checkUniqueUserName->name()] = $checkUniqueUserName;
$validator[$checkEmailNotUsed->name()] = $checkEmailNotUsed;
$results = array();
foreach ($validator as $v)
{
$result[$v->getValidatorName()] = $v->execute($userInfo);
}
class CheckUniqueUserName()
{
public function execute($userInfo)
{
// SQL blah blah blah
if ($bNameUnique)
return array ('success' => 1)
else
return array ('success' => 0, 'error' => "$name is in used", 'error_code' => 'duplicate_name);
}
}
At the end, you will have a results array, each filled with a validation process, and you know which has failed, and which has not. This can then be passed to the client-side for further processing, like highlighting the failed fields. The error_code an be used to look up the proper error message and formatting applied to it.
I am not really sure about what you mean by call-backs though.