SQL Injections
In plain PHP, we need to bind all the parameters on SQL queries. But in Laravel, we have the query builder and Eloquent ORM that provides automatic protection against SQL injections by adding param binding by default. Even with this, you should watch out for malicious requests, like for example:
User::query()->create($request->all());
This code could lead to a mass assignment. In this case, a user can send a payload like this:
{
"name": "Basim Ghouri",
"email": "basim@gmail.com",
"role_id": "admin"
}
Another code that could lead to the same issue could be:
$user->fill($request->all());
$user->save();
In this example, we are hydrating an eloquent model with all the data from a request and then saving it.
A malicious user can try with different payloads. Or, they can add extra inputs with different names and try to find a weak implementation like this.
Hopefully, with this example, we can see that we need to take care of mass assignments. We cannot trust any user request, because any user can open the browser inspector and add an input in a monolith or modify the payload from an API.
Laravel provides different ways to handle this:
Set Fillable Property
We can prevent mass assignment by adding explicitly the fields that a model contains by using protected properties, "fillable" or "guarded":
protected $fillable = ['name', 'email', 'password', 'role_id'];
In this case, we are adding explicitly the columns that a model contains. You can use the guarded property as an empty array. Personally, I do not like this approach as many projects have more than one developer and there is no guaranty that other developers would validate the data.
The forceFill() method can skip this protection, so take care when you are using this method.
Validate Request Data
You should validate any type of resource no matter where it came from. The best policy is to not trust the user. Laravel provides FormRequest so we only need to create one with artisan:
php artisan make:request UserRequest
You can define the rules to validate your requests:
public function authorize()
{
return $this->user()->check();
}
public function rules()
{
return [
'name' => ['required', 'string', 'min:5', 'max:255'],
'email' => ['required', 'email', 'unique:users'],
'password' => ['required', Password::default()]
];
}
The authorize method must return a boolean. It is a convenient way to return an authorization validation before starting to validate the requested content. This is something to take in mind and it would apply in any route that has the middleware auth for web or sanctum/API if you are using token-based authentication.
The rules method returns an array with the rules that are validating your request. You can use a lot of rules out of the box or create your own custom rules. If you are interested to dive in deeper into this topic, you can find all the rules in the doc: https://laravel.com/docs/8.x/validation#available-validation-rules.
Top comments (2)
I have read all 4 parts of this article. thanks for the info
Follow And like for more laravel security parts