Skip to main content
Back to Blog Security

Securing Your Laravel Application: Essential Practices

Abdelrahman Shrief
Abdelrahman Shrief January 25, 2026
5 min read

Input Validation

Always validate user input using Form Requests:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Password;

class RegisterRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        return [
            'name' => ['required', 'string', 'max:255'],
            'email' => [
                'required',
                'string',
                'email:rfc,dns',
                'max:255',
                'unique:users',
            ],
            'password' => [
                'required',
                'confirmed',
                Password::min(8)
                    ->mixedCase()
                    ->numbers()
                    ->symbols()
                    ->uncompromised(),
            ],
        ];
    }
}

SQL Injection Prevention

Eloquent and Query Builder protect against SQL injection by default, but be careful with raw queries:

<?php

// DANGEROUS - SQL Injection vulnerability
$users = DB::select("SELECT * FROM users WHERE name = '" . $name . "'");

// SAFE - Using parameter binding
$users = DB::select("SELECT * FROM users WHERE name = ?", [$name]);

// SAFE - Using Eloquent
$users = User::where('name', $name)->get();

// SAFE - Using whereRaw with bindings
$users = User::whereRaw('LOWER(name) = ?', [strtolower($name)])->get();

XSS Prevention

Blade automatically escapes output. Use {!! !!} sparingly and only with trusted content:

<?php

// In your Blade template:

// SAFE - Escaped output
{{ $user->name }}
{{ $user->bio }}

// DANGEROUS - Unescaped output (only use with trusted content)
{!! $post->content !!}

// If you must render HTML, sanitize it first:
{!! clean($post->content) !!}  // Using a sanitizer package

Authorization with Policies

Use policies to control access to resources:

<?php

namespace App\Policies;

use App\Models\Post;
use App\Models\User;

class PostPolicy
{
    public function view(User $user, Post $post): bool
    {
        return $post->is_published || $user->id === $post->user_id;
    }

    public function update(User $user, Post $post): bool
    {
        return $user->id === $post->user_id;
    }

    public function delete(User $user, Post $post): bool
    {
        return $user->id === $post->user_id || $user->isAdmin();
    }
}

// In controller:
public function update(UpdatePostRequest $request, Post $post)
{
    $this->authorize('update', $post);
    // ...
}

Rate Limiting

Protect against brute force attacks:

<?php

// In routes/api.php
Route::middleware(['throttle:api'])->group(function () {
    Route::post('/login', [AuthController::class, 'login']);
});

// Custom rate limiter in AppServiceProvider
RateLimiter::for('login', function (Request $request) {
    return [
        Limit::perMinute(5)->by($request->ip()),
        Limit::perMinute(10)->by($request->input('email')),
    ];
});

Conclusion

Security should be built into your application from the start. Validate all input, use Laravel's built-in protections, and always follow the principle of least privilege.


Written by Abdo Shrief Senior Laravel Developer based in Cairo.
https://www.abdoshrief.tech

Abdelrahman Shrief
Abdelrahman Shrief Senior Backend Developer

Share this post

Need Help With Your Project?

Let's discuss how I can help bring your ideas to life with expert backend development.

Get in Touch