ASP.NET Core`da Güvenlik İçin 15 Kural - Kod Örnekleri

ASP NET Core da Güvenlik İçin 15 Kural Kod Örnekleri

ASP.NET Core projelerinde güvenliği artırmak için kod örnekleri ile beraner 15 temel kural paylaşmak istedim.

1. Ara katman yazılımı kullanarak HTTPS'yi zorunlu kılın ve tüm HTTP trafiğini yönlendirin

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpsRedirection(options =>
{
    options.RedirectStatusCode = StatusCodes.Status308PermanentRedirect;
    options.HttpsPort = 443;
});

var app = builder.Build();

app.UseHttpsRedirection();

app.MapGet("/", () => "HTTPS Zorunlu!");

app.Run();

2. Uç noktaları [Authorize] ve JWT kimlik doğrulamasıyla güvenli hale getirin

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

[Authorize]
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
    [HttpGet]
    public IActionResult GetOrders()
    {
        return Ok(new[] { "Order1", "Order2" });
    }
}

3. Veren, hedef kitle ve son kullanma tarihi dahil olmak üzere JWT belirteçlerini doğrulayın

using Microsoft.IdentityModel.Tokens;
using System.Text;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthentication("Bearer")
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidIssuer = "https://auth.myapp.com",

            ValidateAudience = true,
            ValidAudience = "myapp-api",

            ValidateLifetime = true,
            ClockSkew = TimeSpan.Zero,

            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(
                Encoding.UTF8.GetBytes("super-secret-signing-key"))
        };
    });

var app = builder.Build();

app.UseAuthentication();
app.UseAuthorization();

app.MapGet("/secure", [Authorize]() => "JWT ile korunan endpoint");

app.Run();

4. Sabit kodlanmış değerler yerine rol/politika/claim/özel yetkilendirme kullanın

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("AdminOnly", policy =>
        policy.RequireRole("Admin"));
});

var app = builder.Build();

app.UseAuthentication();
app.UseAuthorization();

[Authorize(Policy = "AdminOnly")]
[ApiController]
[Route("api/[controller]")]
public class AdminController : ControllerBase
{
    [HttpDelete("user/{id}")]
    public IActionResult DeleteUser(int id)
    {
        // Sadece Admin rolündeki kullanıcılar erişebilir
        return Ok($"User {id} deleted");
    }
}

app.Run();

5. Gelen tüm modellerde katı giriş doğrulaması uygulayın

using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc;

public class RegisterDto
{
    [Required]
    [EmailAddress]
    public string Email { get; set; }

    [Required]
    [MinLength(8)]
    public string Password { get; set; }
}

[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
    [HttpPost("register")]
    public IActionResult Register([FromBody] RegisterDto dto)
    {
        if (!ModelState.IsValid)
            return BadRequest(ModelState);

        // Kayıt işlemleri
        return Ok("Kayıt başarılı");
    }
}

6. Aşırı gönderimi ve veri enjeksiyonunu önlemek için DTO'ları kullanın

public class UserUpdateDto
{
    public string DisplayName { get; set; }
}

public class User
{
    public int Id { get; set; }
    public string DisplayName { get; set; }
    public string InternalSecret { get; set; }
}

[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
    [HttpPut("{id}")]
    public IActionResult UpdateUser(int id, [FromBody] UserUpdateDto dto)
    {
        // Örnek: veritabanından kullanıcıyı çektiğinizi varsayın
        var user = new User { Id = id, DisplayName = "Old Name", InternalSecret = "DoNotTouch" };

        // Sadece izin verilen alanlar güncellenir
        user.DisplayName = dto.DisplayName;

        return Ok(user);
    }
}

7. Yalnızca güvenilir kaynaklara ve yöntemlere izin vermek için CORS'u yapılandırın

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy("TrustedOrigins", policy =>
    {
        policy.WithOrigins("https://myfrontend.com")
              .AllowAnyHeader()
              .AllowAnyMethod();
    });
});

var app = builder.Build();

app.UseCors("TrustedOrigins");

app.MapGet("/api/data", () => "Sadece güvenilir origin erişebilir");

app.Run();

8. Üretimde ayrıntılı hata mesajlarını gizleyin

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/error");
    app.UseHsts();
}

app.Map("/error", () =>
{
    // Kullanıcıya detay vermeden genel bir hata mesajı
    return Results.Problem("Beklenmeyen bir hata oluştu.");
});

app.MapGet("/throw", () =>
{
    throw new Exception("Detaylı hata - sadece loglarda");
});

app.Run();

9. Kaba kuvvet saldırılarını ve kötüye kullanımı engellemek için hız sınırlaması uygulayın

using Microsoft.AspNetCore.RateLimiting;
using System.Threading.RateLimiting;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRateLimiter(options =>
{
    options.AddFixedWindowLimiter("fixed", limiterOptions =>
    {
        limiterOptions.PermitLimit = 10;              // 10 istek
        limiterOptions.Window = TimeSpan.FromSeconds(10); // 10 saniyede
        limiterOptions.QueueLimit = 0;
    });
});

var app = builder.Build();

app.UseRateLimiter();

app.MapGet("/api/limited", () => "Rate limited endpoint")
   .RequireRateLimiting("fixed");

app.Run();

10. Belirteçleri, parolaları ve hassas kullanıcı verilerini kaydetmekten kaçının

using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Identity;

public class AuthService
{
    private readonly ILogger<AuthService> _logger;
    private readonly IPasswordHasher<string> _passwordHasher;

    public AuthService(ILogger<AuthService> logger, IPasswordHasher<string> passwordHasher)
    {
        _logger = logger;
        _passwordHasher = passwordHasher;
    }

    public void Login(string username, string password)
    {
        // HATALI: _logger.LogInformation("User {User} logged in with password {Password}", username, password);
        _logger.LogInformation("User {User} attempted login", username);

        // Parola asla düz metin olarak saklanmaz
        var hashed = _passwordHasher.HashPassword(username, password);

        // hashed değeri veritabanında saklanabilir
    }
}

11. HSTS ve X-Content-Type-Options gibi güvenlik başlıkları ekleyin

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

// HSTS (sadece HTTPS üzerinde çalışırken)
if (!app.Environment.IsDevelopment())
{
    app.UseHsts();
}

app.Use(async (context, next) =>
{
    context.Response.Headers["X-Content-Type-Options"] = "nosniff";
    context.Response.Headers["X-Frame-Options"] = "DENY";
    context.Response.Headers["X-XSS-Protection"] = "1; mode=block";
    await next();
});

app.MapGet("/", () => "Güvenlik başlıkları eklendi");

app.Run();

12. Bilinen güvenlik açıklarını düzeltmek için NuGet paketlerini düzenli olarak güncelleyin

REM Komut satırı örnekleri (Windows)

dotnet list package --outdated

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer --version 8.0.0

REM CI/CD pipeline içinde periyodik kontrol script'i yazılabilir

13. Çerezleri HttpOnly, Secure ve SameSite özellikleriyle ayarlayın

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/set-cookie", (HttpContext context) =>
{
    context.Response.Cookies.Append("session-id", "abc123", new CookieOptions
    {
        HttpOnly = true,
        Secure = true,
        SameSite = SameSiteMode.Strict,
        Expires = DateTimeOffset.UtcNow.AddHours(1)
    });

    return "Güvenli çerez ayarlandı";
});

app.Run();

14. Kullanılmayan uç noktaları ve gereksiz denetleyicileri kaldırın

// En iyi yaklaşım: kullanılmayan controller ve endpoint'leri projeden tamamen silmek

// Geçici olarak gizlemek için:
using Microsoft.AspNetCore.Mvc;

[ApiExplorerSettings(IgnoreApi = true)]
[ApiController]
[Route("api/[controller]")]
public class LegacyController : ControllerBase
{
    [HttpGet("old-endpoint")]
    public IActionResult OldEndpoint()
    {
        return NotFound("Bu endpoint artık kullanılmıyor");
    }
}

15. Kullanıcıları yönetirken güçlü parola politikaları kullanın

using Microsoft.AspNetCore.Identity;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddIdentityCore<IdentityUser>(options =>
{
    options.Password.RequireDigit = true;
    options.Password.RequiredLength = 8;
    options.Password.RequireUppercase = true;
    options.Password.RequireLowercase = true;
    options.Password.RequireNonAlphanumeric = true;
})
.AddRoles<IdentityRole>()
.AddSignInManager()
.AddDefaultTokenProviders();

var app = builder.Build();

app.MapGet("/", () => "Güçlü parola politikaları yapılandırıldı");

app.Run();