add security
This commit is contained in:
parent
76ee85ab1f
commit
40186c6149
5
.env
5
.env
@ -17,3 +17,8 @@ DATABASE_URL="postgresql://${DB_USER:-db}:${DB_PW:-db}@${DB_HOST:-db}:${DB_PORT:
|
||||
STRIPE_PUBLIC_KEY=${STRIPE_PUBLIC_KEY}
|
||||
STRIPE_SECRET_KEY=${STRIPE_PUBLIC_KEY}
|
||||
###
|
||||
|
||||
### ADMIN PANEL
|
||||
USER_PASSWORD=${USER_PASSWORD}
|
||||
ADMIN_PASSWORD=${ADMIN_PASSWORD}
|
||||
###
|
4
.env.dev
4
.env.dev
@ -1,4 +1,6 @@
|
||||
|
||||
###> symfony/framework-bundle ###
|
||||
APP_SECRET=5a866a6ab3ce4ef99240ba643868b123
|
||||
###< symfony/framework-bundle ###
|
||||
|
||||
USER_PASSWORD=\$2y\$13\$z/XlUykvakLzDR8TeFrQk.jmGuOKOcULlMY/m17aWmkY4f4NrIaam
|
||||
ADMIN_PASSWORD=\$2y\$13\$z/XlUykvakLzDR8TeFrQk.jmGuOKOcULlMY/m17aWmkY4f4NrIaam
|
@ -7,8 +7,8 @@ security:
|
||||
users_in_memory:
|
||||
memory:
|
||||
users:
|
||||
user: { password: '123', roles: ['ROLE_ADMIN'] }
|
||||
admin: { password: '123', roles: ['ROLE_SUPER_ADMIN'] }
|
||||
user: { password: '%env(USER_PASSWORD)%', roles: ['ROLE_ADMIN'] }
|
||||
admin: { password: '%env(ADMIN_PASSWORD)%', roles: ['ROLE_SUPER_ADMIN'] }
|
||||
|
||||
firewalls:
|
||||
dev:
|
||||
@ -20,7 +20,10 @@ security:
|
||||
custom_authenticator: App\Security\AdminPanelAuthenticator
|
||||
form_login:
|
||||
login_path: /admin/login
|
||||
|
||||
check_path: /admin/login
|
||||
logout:
|
||||
path: /admin/logout
|
||||
target: /admin/login
|
||||
# activate different ways to authenticate
|
||||
# https://symfony.com/doc/current/security.html#the-firewall
|
||||
|
||||
@ -29,6 +32,10 @@ security:
|
||||
|
||||
# Easy way to control access for large sections of your site
|
||||
# Note: Only the *first* access control that matches will be used
|
||||
|
||||
role_hierarchy:
|
||||
ROLE_SUPER_ADMIN: ROLE_ADMIN
|
||||
|
||||
access_control:
|
||||
- { path: ^/admin/login, roles: PUBLIC_ACCESS }
|
||||
- { path: ^/admin, roles: ROLE_ADMIN }
|
||||
|
@ -7,12 +7,16 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
|
||||
|
||||
class SecurityController extends AbstractController
|
||||
{
|
||||
#[Route(path: '/admin/login', name: 'admin_login', methods: Request::METHOD_GET)]
|
||||
public function login(): Response
|
||||
#[Route(path: '/admin/login', name: 'admin_login', methods: [Request::METHOD_GET, Request::METHOD_POST])]
|
||||
public function login(AuthenticationUtils $authenticationUtils): Response
|
||||
{
|
||||
return $this->render('admin/login.html.twig');
|
||||
return $this->render('admin/login.html.twig', [
|
||||
'last_username' => $authenticationUtils->getLastUsername(),
|
||||
'error' => $authenticationUtils->getLastAuthenticationError(),
|
||||
]);
|
||||
}
|
||||
}
|
23
src/DataObjects/LoginData.php
Normal file
23
src/DataObjects/LoginData.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\DataObjects;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class LoginData
|
||||
{
|
||||
public function __construct(
|
||||
public ?string $username = '',
|
||||
public ?string $password = ''
|
||||
) {
|
||||
}
|
||||
|
||||
public static function fromRequest(Request $request): self
|
||||
{
|
||||
return new self(
|
||||
$request->get('_username'),
|
||||
$request->get('_password'),
|
||||
);
|
||||
}
|
||||
}
|
@ -2,29 +2,41 @@
|
||||
|
||||
namespace App\Security;
|
||||
|
||||
use App\DataObjects\LoginData;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
|
||||
use Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
||||
|
||||
class AdminPanelAuthenticator extends AbstractAuthenticator
|
||||
{
|
||||
public function supports(Request $request): ?bool
|
||||
{
|
||||
return str_starts_with($request->getRequestUri(), '/admin');
|
||||
return str_starts_with($request->getRequestUri(), '/admin') && $request->isMethod(Request::METHOD_POST);
|
||||
}
|
||||
|
||||
public function authenticate(Request $request): Passport
|
||||
{
|
||||
throw new CustomUserMessageAuthenticationException();
|
||||
$data = LoginData::fromRequest($request);
|
||||
|
||||
if ($request->isMethod(Request::METHOD_POST) && (!$data->password || !$data->username)) {
|
||||
dd($data);
|
||||
throw new CustomUserMessageAuthenticationException();
|
||||
}
|
||||
|
||||
return new Passport(new UserBadge($data->username), new PasswordCredentials($data->password), [new RememberMeBadge()]);
|
||||
}
|
||||
|
||||
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
|
||||
{
|
||||
return null;
|
||||
return new RedirectResponse('/admin');
|
||||
}
|
||||
|
||||
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
|
||||
|
@ -4,10 +4,14 @@
|
||||
<div class="min-h-screen flex items-center justify-center bg-[#0a0a0a] px-4 sm:px-6 lg:px-8">
|
||||
<div class="w-full max-w-[90%] sm:max-w-md">
|
||||
<div class="text-center mb-8">
|
||||
<h2 class="text-xl sm:text-2xl font-medium text-gray-200">Administration</h2>
|
||||
<h2 class="text-xl sm:text-2xl font-medium text-gray-200">Abiball Admin Panel</h2>
|
||||
</div>
|
||||
|
||||
<form method="post" class="space-y-4 sm:space-y-6">
|
||||
{% if error %}
|
||||
{{ error.message }}
|
||||
{% endif %}
|
||||
|
||||
<form method="post" class="space-y-4 sm:space-y-6" action="{{ path('admin_login') }}">
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}" />
|
||||
|
||||
<div>
|
||||
@ -21,7 +25,7 @@
|
||||
name="_username"
|
||||
required
|
||||
class="block w-full pl-9 sm:pl-10 py-2 sm:py-2.5 text-sm sm:text-base bg-[#2a2a2a] border border-[#333333] text-gray-200 rounded-md focus:ring-2 focus:ring-orange-500/20 focus:border-orange-500 transition-colors"
|
||||
placeholder="admin@example.com" />
|
||||
placeholder="username" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -40,15 +44,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<input type="checkbox"
|
||||
id="remember_me"
|
||||
name="_remember_me"
|
||||
class="h-3.5 w-3.5 sm:h-4 sm:w-4 bg-[#2a2a2a] border-[#333333] rounded text-orange-500 focus:ring-orange-500/20" />
|
||||
<label for="remember_me" class="ml-2 block text-xs sm:text-sm text-gray-300">
|
||||
Angemeldet bleiben
|
||||
</label>
|
||||
</div>
|
||||
<hr>
|
||||
|
||||
<div>
|
||||
<button type="submit"
|
||||
|
Loading…
x
Reference in New Issue
Block a user