Symfony REST API Guvenliği: Kimlik Doğrulama, JWT ve 2026 Mulakat Soruları
Symfony REST API guvenliği icin kapsamlı rehber. JWT kimlik doğrulama, guvenlik en iyi uygulamaları ve 2026 mulakat sorularına hazırlık.

REST API guvenliği modern web uygulamalarının temel taşlarından birini oluşturmaktadır. Symfony ekosistemi, geliştiricilere guclü koruma mekanizmalarını uygulamak icin gelişmiş araclar ve bileşenler sunmaktadır. Bu rehber, API guvenliğinin en onemli yonlerini ele almakta ve 2026 yılı mulakat sorularına hazırlık sağlamaktadır.
Symfony Security Component 7.x surumunde JWT token desteği ve firewall yonetimi konusunda onemli iyileştirmeler yapılmıştır. Uygulama oncesinde guncel dokumantasyonu incelemek faydalı olacaktır.
Symfony'de Guvenlik Mimarisi
Symfony Security, uygulamanın farklı koruma katmanlarından sorumlu birkaç temel bileşenden oluşmaktadır. Bu mimariyi anlamak, guvenlik yapılandırmasının doğru şekilde gercekleştirilmesi icin zorunludur.
Security bileşeni iki ana alana ayrılmaktadır: kimlik doğrulama (authentication) ve yetkilendirme (authorization). Kimlik doğrulama kullanıcının kimliğini doğrularken, yetkilendirme erişilebilir kaynakları ve işlemleri belirlemektedir.
# config/packages/security.yaml
security:
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: "auto"
providers:
app_user_provider:
entity:
class: App\Entity\User
property: email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
api:
pattern: ^/api
stateless: true
jwt: ~
main:
lazy: true
provider: app_user_providerJWT Authentication Uygulaması
JSON Web Token (JWT), taraflar arasında guvenli bilgi alışverişini JSON nesnesi olarak sağlayan bir standarttır. REST API bağlamında JWT tokenları, sunucu tarafında oturum saklamaya gerek kalmadan isteklerin kimlik doğrulamasını gercekleştirmektedir.
LexikJWTAuthenticationBundle paketinin kurulumu yapılandırma surecini başlatmaktadır:
composer require lexik/jwt-authentication-bundleKriptografik anahtarların oluşturulması icin aşağıdaki komutlar calistırılmalıdır:
php bin/console lexik:jwt:generate-keypairPaketin yapılandırma dosyasındaki ayarları:
# config/packages/lexik_jwt_authentication.yaml
lexik_jwt_authentication:
secret_key: "%env(resolve:JWT_SECRET_KEY)%"
public_key: "%env(resolve:JWT_PUBLIC_KEY)%"
pass_phrase: "%env(JWT_PASSPHRASE)%"
token_ttl: 3600
token_extractors:
authorization_header:
enabled: true
prefix: Bearer
name: AuthorizationGiriş Endpoint'i ve Token Uretimi
Kullanıcı kimlik doğrulaması ve JWT token uretiminden sorumlu controller:
<?php
namespace App\Controller\Api;
use App\Repository\UserRepository;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Attribute\Route;
#[Route("/api")]
class AuthController extends AbstractController
{
public function __construct(
private UserRepository $userRepository,
private UserPasswordHasherInterface $passwordHasher,
private JWTTokenManagerInterface $jwtManager,
) {}
#[Route("/login", name: "api_login", methods: ["POST"])]
public function login(Request $request): JsonResponse
{
$data = json_decode($request->getContent(), true);
$user = $this->userRepository->findOneBy(["email" => $data["email"] ?? ""]);
if (!$user || !$this->passwordHasher->isPasswordValid($user, $data["password"] ?? "")) {
return new JsonResponse(["error" => "Invalid credentials"], 401);
}
$token = $this->jwtManager->create($user);
return new JsonResponse([
"token" => $token,
"expires_in" => 3600,
]);
}
}Token Doğrulama ve Yenileme
Token yenileme mekanizması, yeniden giriş gerektirmeden oturum surekliliğini sağlamaktadır:
<?php
namespace App\Service;
use App\Entity\RefreshToken;
use App\Repository\RefreshTokenRepository;
use Doctrine\ORM\EntityManagerInterface;
use Lexik\Bundle\JWTAuthenticationBundle\Services\JWTTokenManagerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
class TokenRefreshService
{
public function __construct(
private RefreshTokenRepository $refreshTokenRepository,
private EntityManagerInterface $entityManager,
private JWTTokenManagerInterface $jwtManager,
) {}
public function createRefreshToken(UserInterface $user): string
{
$token = bin2hex(random_bytes(64));
$refreshToken = new RefreshToken();
$refreshToken->setToken(hash("sha256", $token));
$refreshToken->setUser($user);
$refreshToken->setExpiresAt(new \DateTimeImmutable("+30 days"));
$this->entityManager->persist($refreshToken);
$this->entityManager->flush();
return $token;
}
public function refresh(string $token): ?array
{
$hashedToken = hash("sha256", $token);
$refreshToken = $this->refreshTokenRepository->findOneBy(["token" => $hashedToken]);
if (!$refreshToken || $refreshToken->isExpired()) {
return null;
}
$user = $refreshToken->getUser();
$jwt = $this->jwtManager->create($user);
return [
"token" => $jwt,
"refresh_token" => $this->rotateRefreshToken($refreshToken, $user),
];
}
private function rotateRefreshToken(RefreshToken $oldToken, UserInterface $user): string
{
$this->entityManager->remove($oldToken);
return $this->createRefreshToken($user);
}
}Erişim Kontrolu ve Voter'lar
Symfony'deki Voter sistemi karmaşık yetkilendirme mantığının uygulanmasını mumkun kılmaktadır:
<?php
namespace App\Security\Voter;
use App\Entity\Article;
use App\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class ArticleVoter extends Voter
{
public const EDIT = "ARTICLE_EDIT";
public const DELETE = "ARTICLE_DELETE";
public const VIEW = "ARTICLE_VIEW";
protected function supports(string $attribute, mixed $subject): bool
{
return in_array($attribute, [self::EDIT, self::DELETE, self::VIEW])
&& $subject instanceof Article;
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{
$user = $token->getUser();
if (!$user instanceof User) {
return false;
}
/** @var Article $article */
$article = $subject;
return match($attribute) {
self::VIEW => $this->canView($article, $user),
self::EDIT => $this->canEdit($article, $user),
self::DELETE => $this->canDelete($article, $user),
default => false,
};
}
private function canView(Article $article, User $user): bool
{
return $article->isPublished() || $article->getAuthor() === $user;
}
private function canEdit(Article $article, User $user): bool
{
return $article->getAuthor() === $user || in_array("ROLE_EDITOR", $user->getRoles());
}
private function canDelete(Article $article, User $user): bool
{
return in_array("ROLE_ADMIN", $user->getRoles());
}
}Rate Limiting ve Saldırı Koruması
İstek sınırlandırma, API'yi brute-force saldırılarına karşı korumaktadır:
<?php
namespace App\EventListener;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\RateLimiter\RateLimiterFactory;
#[AsEventListener(event: "kernel.request", priority: 100)]
class RateLimitListener
{
public function __construct(
private RateLimiterFactory $apiLimiter,
) {}
public function __invoke(RequestEvent $event): void
{
$request = $event->getRequest();
if (!str_starts_with($request->getPathInfo(), "/api")) {
return;
}
$limiter = $this->apiLimiter->create($request->getClientIp());
$limit = $limiter->consume();
if (!$limit->isAccepted()) {
$response = new JsonResponse(
["error" => "Too many requests", "retry_after" => $limit->getRetryAfter()->getTimestamp()],
429
);
$response->headers->set("Retry-After", $limit->getRetryAfter()->getTimestamp());
$event->setResponse($response);
}
}
}Girdi Doğrulama
Girdi verilerinin doğru şekilde doğrulanması ilk savunma hattını oluşturmaktadır:
<?php
namespace App\Dto;
use Symfony\Component\Validator\Constraints as Assert;
class CreateUserRequest
{
#[Assert\NotBlank]
#[Assert\Email]
public string $email;
#[Assert\NotBlank]
#[Assert\Length(min: 8, max: 128)]
#[Assert\PasswordStrength(minScore: 3)]
public string $password;
#[Assert\NotBlank]
#[Assert\Length(min: 2, max: 100)]
public string $name;
}Symfony mülakatlarında başarılı olmaya hazır mısın?
İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.
Mulakat Soruları - API Guvenliği
2026 yılında teknik mulakatlarda adayların aşağıdaki sorularla karşılaşması beklenmektedir:
Kimlik doğrulama ile yetkilendirme arasındaki fark nedir? Kimlik doğrulama kullanıcının kimliğini doğrulayarak "kim olduğunu" belirlemektedir. Yetkilendirme ise izinleri belirleyerek "ne yapabileceğini" ortaya koymaktadır.
JWT tokenlarının oturumlara gore avantajları nelerdir? JWT tokenları durumsuz (stateless) yapıdadır, bu da uygulamanın kolayca olceklenmesini sağlamaktadır. Sunucu tarafında oturum verisi saklamayı gerektirmez ve mikroservis mimarisinde mukemmel şekilde calışmaktadır.
API'yi CSRF saldırılarına karşı nasıl korunur? Authorization başlığında JWT tokenları kullanan REST API'leri CSRF saldırılarına doğal olarak dayanıklıdır, cunku tarayıcılar cross-origin isteklere otomatik olarak başlık eklememektedir.
Refresh token nedir ve neden gereklidir? Refresh token, yeniden giriş yapmadan yeni bir access token almayı mumkun kılmaktadır. Bu sayede kullanıcı rahatlığı korunurken kısa omurlu access tokenları kullanılabilmektedir.
Symfony'de rol hiyerarşisi nasıl uygulanır? Symfony, security.yaml yapılandırması aracılığıyla rol hiyerarşisini desteklemektedir. Ust rol otomatik olarak alt rollerin tum yetkilerini icermektedir.
security:
role_hierarchy:
ROLE_ADMIN: [ROLE_EDITOR, ROLE_USER]
ROLE_EDITOR: [ROLE_USER]Hata Yonetimi ve Gunlukleme
Guvenlikle ilgili istisnaların doğru şekilde ele alınması:
<?php
namespace App\EventListener;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Psr\Log\LoggerInterface;
#[AsEventListener(event: "kernel.exception")]
class SecurityExceptionListener
{
public function __construct(
private LoggerInterface $securityLogger,
) {}
public function __invoke(ExceptionEvent $event): void
{
$exception = $event->getThrowable();
$request = $event->getRequest();
if ($exception instanceof AuthenticationException) {
$this->securityLogger->warning("Authentication failed", [
"ip" => $request->getClientIp(),
"path" => $request->getPathInfo(),
]);
$event->setResponse(new JsonResponse(
["error" => "Authentication required"],
401
));
return;
}
if ($exception instanceof AccessDeniedException) {
$this->securityLogger->warning("Access denied", [
"ip" => $request->getClientIp(),
"path" => $request->getPathInfo(),
]);
$event->setResponse(new JsonResponse(
["error" => "Access denied"],
403
));
}
}
}Sonuc
Symfony'de REST API guvenliği, JWT kimlik doğrulama, Voter tabanlı yetkilendirme, girdi doğrulama ve yaygın saldırılara karşı korumayı kapsayan cok katmanlı bir yaklaşım gerektirmektedir. Bu mekanizmaları anlamak ve uygulayabilmek, 2026 yılında teknik mulakatlara hazırlanan her Symfony geliştiricisi icin kritik bir yetkinlik oluşturmaktadır. Security Component guncellemelerini ve guvenlik en iyi uygulamalarını duzenli olarak takip etmek, dayanıklı ve guvenli uygulamalar oluşturmayı mumkun kılmaktadır.
Symfony kodundaki hatayı bulabilir misin?
Gerçek bir kod parçası, gizli bir hata, günde bir deneme. Denemek için hesap gerekmez.

Yazan:
Anthony Fillion-MailletSharpSkill kurucusu
10 yılı aşkın süredir fullstack geliştirici. SharpSkill’i yönetiyor ve burada yayımlanan her şeyden sorumlu.
26 Ağustos 2026 tarihinde güncellendi
Paylaş
İlgili makaleler

2026'da Symfony REST API Güvenliği: OAuth2, Rate Limiting ve Mülakat Soruları
Symfony REST API'lerini OAuth2 token introspection, rate limiting ve JWT doğrulama ile güvence altına alma rehberi. Symfony 7.3 güvenlik özellikleri ve mülakat soruları.

2026'da Symfony ile API Platform: Mimari, State Providers ve Mülakat Soruları
API Platform 4.2 ile Symfony'yi öğrenin: State Providers, Processors, Object Mapper, JSON Streamer ve performans optimizasyonları. Deneyimli geliştiriciler için sık sorulan mülakat soruları.

API Platform GraphQL Symfony: Şemalar, Mutasyonlar ve Mülakat Soruları 2026
Symfony'de API Platform ile GraphQL entegrasyonu için kapsamlı rehber. Şemalar, sorgular, mutasyonlar, resolver'lar, güvenlik ve mülakat soruları.