Security (R6.2): Haertung nach Audit
- Security-Header-Middleware (nosniff, X-Frame-Options, Referrer-/ Permissions-Policy) global, proxy-unabhaengig; CSP bewusst separat. - Firmenlogo-Upload im Create-Formular durch den ImageService-Pfad ersetzt (Mime-Whitelist ohne SVG, Re-Encode, UUID-Name) - vorher rohe store()-Ablage ohne Server-Validierung (SVG/XSS moeglich). - Rate-Limits ergaenzt: Passwort-Reset (3/E-Mail + 15/IP pro Std.), Registrierung (10/IP pro Std.), throttle auf magic-login- und pm-vorschau-Consume-Routen (Defense-in-Depth). - EnsureUserIsCustomer als persistente Livewire-Middleware (symmetrisch zum Admin-Gate, greift auch bei Folge-Requests). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
acb2a19aff
commit
89550dac99
9 changed files with 212 additions and 9 deletions
|
|
@ -1,6 +1,9 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Livewire\Attributes\Layout;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
|
|
@ -16,10 +19,41 @@ new #[Layout('components.layouts.auth.pressekonto', ['heading' => 'Passwort verg
|
|||
'email' => ['required', 'string', 'email'],
|
||||
]);
|
||||
|
||||
// Drosseln wie beim Anmeldelink: pro E-Mail (Mail-Fluten eines
|
||||
// Postfachs) und pro IP (Durchprobieren vieler Adressen). Der
|
||||
// Password-Broker drosselt zusätzlich nur pro Nutzer (60s).
|
||||
$this->ensureIsNotRateLimited();
|
||||
RateLimiter::hit($this->throttleKey(), 3600);
|
||||
RateLimiter::hit($this->ipThrottleKey(), 3600);
|
||||
|
||||
Password::sendResetLink($this->only('email'));
|
||||
|
||||
session()->flash('status', __('A reset link will be sent if the account exists.'));
|
||||
}
|
||||
|
||||
protected function ensureIsNotRateLimited(): void
|
||||
{
|
||||
$withinEmail = ! RateLimiter::tooManyAttempts($this->throttleKey(), 3);
|
||||
$withinIp = ! RateLimiter::tooManyAttempts($this->ipThrottleKey(), 15);
|
||||
|
||||
if ($withinEmail && $withinIp) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'email' => __('Zu viele Anfragen. Bitte versuchen Sie es später erneut.'),
|
||||
]);
|
||||
}
|
||||
|
||||
protected function throttleKey(): string
|
||||
{
|
||||
return 'password-reset|'.Str::transliterate(Str::lower($this->email));
|
||||
}
|
||||
|
||||
protected function ipThrottleKey(): string
|
||||
{
|
||||
return 'password-reset-ip|'.request()->ip();
|
||||
}
|
||||
}; ?>
|
||||
|
||||
<div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue