PHP

Artigo 44 — Autenticação e Autorização no Laravel Já leu

5 min de leitura

Artigo 44 — Autenticação e Autorização no Laravel
Autenticação responde "quem é você?" — verifica identidade. Autorização responde "o que você pode fazer?" — verifica permissões. Laravel oferece infraestrutura

Artigo 44 — Autenticação e Autorização no Laravel

Módulo 7 · Semana 44 · Nível: Intermediário–Avançado


Introdução

Autenticação responde "quem é você?" — verifica identidade. Autorização responde "o que você pode fazer?" — verifica permissões. Laravel oferece infraestrutura completa para ambas, com flexibilidade para ir do simples ao complexo conforme o sistema cresce.


Laravel Breeze — scaffolding de autenticação

Para a maioria dos projetos, o ponto de partida é o Laravel Breeze:

composer require laravel/breeze --dev
php artisan breeze:install blade   # ou: react, vue, api
php artisan migrate
npm install && npm run dev

O Breeze instala: rotas de login/registro/logout/reset de senha, controllers, views Blade completas, e middleware de autenticação — tudo pronto para customizar.


Autenticação manual

Entender como funciona por baixo é fundamental:

<?php
declare(strict_types=1);

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;

class LoginController extends Controller
{
    public function store(Request $request): RedirectResponse
    {
        $credenciais = $request->validate([
            'email' => ['required', 'email'],
            'senha' => ['required'],
        ]);

        // Auth::attempt verifica email + senha e cria a sessão
        if (!Auth::attempt(
            ['email' => $credenciais['email'], 'password' => $credenciais['senha']],
            $request->boolean('lembrar'),  // "Lembrar de mim"
        )) {
            throw ValidationException::withMessages([
                'email' => 'Email ou senha incorretos.',
            ]);
        }

        // Regenera session ID — previne session fixation
        $request->session()->regenerate();

        return redirect()->intended(route('dashboard'));
    }

    public function destroy(Request $request): RedirectResponse
    {
        Auth::logout();
        $request->session()->invalidate();
        $request->session()->regenerateToken();

        return redirect()->route('login');
    }
}

Middleware de autenticação

<?php
// routes/web.php

// Proteger rotas com middleware auth
Route::middleware('auth')->group(function () {
    Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard');
    Route::resource('pedidos', PedidoController::class);
});

// Redirecionar usuários já autenticados
Route::middleware('guest')->group(function () {
    Route::get('/login', [LoginController::class, 'create'])->name('login');
    Route::post('/login', [LoginController::class, 'store']);
});

Autorização com Gates e Policies

Gates — regras simples de autorização definidas em closures:

<?php
// app/Providers/AppServiceProvider.php

use Illuminate\Support\Facades\Gate;

public function boot(): void
{
    Gate::define('editar-produto', function (User $usuario, Produto $produto) {
        return $usuario->isAdmin() || $produto->criado_por === $usuario->id;
    });

    Gate::define('acessar-admin', function (User $usuario) {
        return $usuario->role === 'admin';
    });
}

// Uso no controller:
public function update(Request $request, Produto $produto): RedirectResponse
{
    Gate::authorize('editar-produto', $produto); // lança 403 se não autorizado

    $produto->update($request->validated());
    return redirect()->route('produtos.show', $produto);
}

// Verificação sem lançar exceção:
if (Gate::allows('acessar-admin')) {
    // mostra menu admin
}

if (Gate::denies('editar-produto', $produto)) {
    abort(403);
}

Policies — autorização encapsulada por Model, para projetos maiores:

php artisan make:policy ProdutoPolicy --model=Produto
<?php
namespace App\Policies;

use App\Models\Produto;
use App\Models\User;

class ProdutoPolicy
{
    // Antes de qualquer método — admin pode tudo
    public function before(User $user): ?bool
    {
        if ($user->isAdmin()) return true;
        return null; // null = continua verificando o método específico
    }

    public function viewAny(User $user): bool
    {
        return true; // qualquer usuário autenticado pode listar
    }

    public function view(User $user, Produto $produto): bool
    {
        return $produto->ativo || $user->isAdmin();
    }

    public function create(User $user): bool
    {
        return $user->hasPermission('criar-produto');
    }

    public function update(User $user, Produto $produto): bool
    {
        return $user->id === $produto->criado_por;
    }

    public function delete(User $user, Produto $produto): bool
    {
        return $user->id === $produto->criado_por && $produto->pedidos()->count() === 0;
    }
}
// Registrar a policy (Laravel detecta automaticamente por convenção)
// app/Providers/AppServiceProvider.php
use Illuminate\Support\Facades\Gate;

Gate::policy(Produto::class, ProdutoPolicy::class);

// Uso no controller:
public function update(ProdutoRequest $request, Produto $produto): RedirectResponse
{
    $this->authorize('update', $produto); // usa ProdutoPolicy::update()

    $produto->update($request->validated());
    return redirect()->route('produtos.show', $produto);
}

// No Blade:
@can('update', $produto)
    <a href="{{ route('produtos.edit', $produto) }}">Editar</a>
@endcan

@cannot('delete', $produto)
    <span class="desabilitado">Não pode deletar</span>
@endcannot

Roles e Permissions — sistema completo

Para sistemas maiores, o pacote spatie/laravel-permission é padrão do mercado:

composer require spatie/laravel-permission
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
php artisan migrate
<?php
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;

// Setup de roles e permissions
$admin   = Role::create(['name' => 'admin']);
$editor  = Role::create(['name' => 'editor']);
$cliente = Role::create(['name' => 'cliente']);

Permission::create(['name' => 'criar produto']);
Permission::create(['name' => 'editar produto']);
Permission::create(['name' => 'deletar produto']);
Permission::create(['name' => 'ver pedidos']);

$admin->givePermissionTo(Permission::all());
$editor->givePermissionTo(['criar produto', 'editar produto']);

// Atribuir role ao usuário
$usuario->assignRole('editor');
$usuario->givePermissionTo('ver pedidos');

// Verificações
$usuario->hasRole('admin');
$usuario->can('deletar produto');
$usuario->hasAnyRole(['admin', 'editor']);

// No Blade:
@role('admin')
    <a href="/admin">Painel Admin</a>
@endrole

@hasanyrole('admin|editor')
    <a href="/produtos/criar">Criar Produto</a>
@endhasanyrole

Resumo

Conceito Função
Auth::attempt() Verifica credenciais e cria sessão
Middleware auth Bloqueia rotas para não autenticados
Gates Regras de autorização simples e pontuais
Policies Autorização encapsulada por Model
$this->authorize() Verifica policy — lança 403 se negado
@can / @cannot Verifica autorização no Blade
spatie/permission Roles e permissions para sistemas complexos

Exercício da semana

  1. Implemente autenticação completa sem Breeze: login, logout, registro, proteção de rotas. Use Auth::attempt() e session()->regenerate() manualmente.

  2. Crie uma PedidoPolicy com métodos view, create, update, cancel. Um usuário só pode ver e cancelar seus próprios pedidos. Admins podem tudo.

  3. Instale spatie/laravel-permission. Crie roles: admin, vendedor, cliente. Defina permissions granulares. Crie um seeder que cria os roles e um admin inicial.

  4. Desafio: implemente autenticação de dois fatores (2FA) simples: após login com senha, se o usuário tiver 2FA ativado, redirecione para uma tela de código TOTP. Use o pacote pragmarx/google2fa-laravel.


Referências

  • Laravel Authentication: https://laravel.com/docs/authentication
  • Laravel Authorization: https://laravel.com/docs/authorization
  • Spatie Laravel Permission: https://spatie.be/docs/laravel-permission
  • Laravel Breeze: https://laravel.com/docs/starter-kits#laravel-breeze

Comentários

Mais em PHP

Artigo 49 — Performance e Otimização
Artigo 49 — Performance e Otimização

Performance não é premature optimization — é entender onde estão os gargalos...

Estruturas de Repetição
Estruturas de Repetição

Se as estruturas de controle ensinam o programa a tomar decis&otilde;es, as e...

APIs REST com PHP
APIs REST com PHP

REST (Representational State Transfer) é o estilo arquitetural dominante para...