Security Tip: Retrieving Request Values
[Tip#40] Let's complete the set of request input helpers and their security implications
Laravel’s Request object (Illuminate\Http\Request
) includes a number of methods for extracting user input. Last week we covered some individual methods, and this time we’re covering the array/collection methods.
// $request->validate()
public function validate(
array $rules = [],
array $messages = [],
array $attributes = []
): array;
My favourite approach: Validates the user input and, if successful, returns an array of only validated input. Usable in most scenarios. 😉
// $request->only()
public function only($keys): array;
Returns only the input values with the specified keys as an array. This allows you to be sure that only the values you intend are returned, avoiding mass-assignment vulnerabilities.
Note that if an input value doesn’t exist, it won’t be included in the output array.
// $request->collect()
public function collect($key = null): \Illuminate\Support\Collection;
Returns the user input in a Laravel Collection, rather than an array. Note this carries the same risks as the all()
method.
You can also specify a single key via the $key
parameter to cast that specific input value as a Collection, or an array of keys to return a Collection with only those keys from the user input.
// $request->all()
public function all($keys = null): array;
Use this method carefully!
Let’s get this one out of the way first. Without the $keys
parameter, it returns all of the user submitted data, regardless of what it is. This makes it trivial to introduce mass-assignment vulnerabilities into your apps.
If you pass the $keys
parameter, it will return an array with every key you specify, even if it doesn’t exist in the user input. The value will be null
instead. This makes the method safe to use, although I would suggest using only()
instead so the parameters cannot be accidently removed.
// $request->except()
public function except($keys): array;
The opposite of only($keys)
. Blocks specific input values from being returned in an array. I can see a use in some situations, but like any blocklist, you need to be careful of what could be included.
As I said above, all of these methods are available on the Illuminate\Http\Request
object, which you’ll typically have injected into your Controller action, or you use the Request
Facade, or request()
helper function:
use \Illuminate\Http\Request;
public function edit(Request $request): View
{
$data = $request->validate([...]);
// ...
}
use \Illuminate\Support\Facades\Request;
public function show(Model $model): View
{
$data = Request::only([...]);
// ...
}
public function show(Model $model): View
{
$data = request()->collect([...]);
// ...
}
My Recommendations
Every use case is different, but my recommendation is to only use validate($rules)
, only($keys)
, and collect($keys)
.
This gives you full control over the user input you accept into your app, significantly reducing the possibility of mass-assignment vulnerabilities (which is incredibly easy to do).
Between those three methods, and the ones we looked last time, you should have the flexibility you need to safely work with user input.
Bonus Methods
As an bonus, there are two more methods you can use:
public function query($key = null, $default = null);
public function post($key = null, $default = null);
These will only input values only from the query string or post data respectively. This allows you to control exactly where the data comes from, if that’s important for your application.