İçeriğe atla

ASP.NET Core 6/HTTPS Bağlantılarla Çalışma

Vikikitap, özgür kütüphane

Günümüzde web siteleri büyük ölçüde HTTPS protokolünü kullanmaktadır. HTTPS protokolü daha hassas verilerin sunuculara gönderilebilmesi ve sunucuların da benzer hassas verileri istemcilere gönderebilmesini sağlamak üzere tasarlanmıştır. Ancak hassas veri göndermesin-göndermesin çoğu web sitesi günümüzde HTTPS protokolünü kullanmaktadır.

HTTPS bağlantıları etkinleştirme

[değiştir]

HTTPS bağlantılarını etkinleştirmek için launchSettings.json dosyası kullanılır. Örnek:

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:5000",
      "sslPort": 0
    }
  },
  "profiles": {
    "Platform": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "http://localhost:5000;https://localhost:5500",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

Bu yapılandırma ayarına göre sunucumuz hem HTTP hem de HTTPS isteklerine cevap verecektir. HTTP isteklerine 5000 portundan, HTTPS isteklerine ise 5500 portundan cevap verecektir. Normalde profesyonel web sitelerinde HTTPS'i etkinleştirmek daha karmaşık bir süreçtir, ancak neyse ki ASP.NET Core geliştirme aşamasında kullanmak üzere bizim için bir test sertifikası sağlamaktadır. Aşağıdaki komutları "Geliştirici PowerShell"i kullanarak .csproj dosyasının olduğu klasörde çalıştırın:

dotnet dev-certs https –-clean
dotnet dev-certs https --trust

ASP.NET Core bu komutlardan sonra uyarı pencereleri çıkarabilir. İlk komut mevcut güvenilen sertifikayı silmektedir. Eğer bu komuttan sonra uyarı penceresi çıkarsa "Yes" diyerek geçin. İkinci komut ise yeni bir güvenilen sertifika yüklemektedir. Bu komutta da uyarı penceresi çıkabilir. Bu pencerede de "Yes" diyebilirsiniz.

HTTPS isteklerini tespit etme

[değiştir]

HttpContext üzerinden erişilen HttpRequest sınıfının IsHttps özelliği geçerli isteğin HTTPS protokolü üzerinden yapılıp yapılmadığını belirtir. Örnek (Program.cs dosyasındaki fallback endpoint eşlemesi):

app.MapFallback(async context => {
    await context.Response.WriteAsync($"HTTPS Request: {context.Request.IsHttps} \n");
    await context.Response.WriteAsync("Hello World!");
});

Gelen isteklere HTTPS'i zorlama

[değiştir]

UseHttpsRedirection() middleware'i bir istek HTTP protokolü üzerinden geldiğinde request pipeline'a kısa devre yaptırır ve geriye aynı URL'in HTTPS versiyonuna yönlendirme içeren bir cevapla geri döner. UseHttpsRedirection() middleware'i kullanıldığı zaman ilk kullanılan middleware'lerden biri olmalıdır. UseHttpsRedirection() middleware'i aşağıdaki şekilde konfigüre edilebilir:

builder.Services.AddHttpsRedirection(opts => {
    opts.RedirectStatusCode = StatusCodes.Status307TemporaryRedirect;
    opts.HttpsPort = 443;
});

UseHttpsRedirection() middleware'inin HTTP talepler için HTTPS versiyonlara yönlendirme cevabıyla geri döndüğünü söylemiştik. İşte bu yönlendirme cevabının durum kodunu RedirectStatusCode özelliğiyle belirtiriz. Varsayılan durumda sunucu HTTPS portunu launchSettings.json dosyasından almaktadır. Ancak bazen projemizi sunucuya deploy ettiğimizde sunucunun başka portu dinlediğini görebiliriz. Böyle bir durumda portu örnekteki gibi elle girebiliriz.

HSTS'i etkinleştirme

[değiştir]

UseHttpsRedirection() middleware'i kullanılarak HTTP'yi HTTPS'e yönlendirmenin bir dezavantajı kullanıcının istediği an HTTP ile istek göndermesine müsaade etmemizdir. Bir istemci HTTP ile istek gönderdiğinde HTTP protokolünü kullanarak HTTPS'e bir yönlendirme cevabı göndeririz. Tarayıcı tekrar HTTPS üzerinden talepte bulunur, bu ikinci talebin cevabı HTTPS ile verilir. Kullanıcı yine HTTP ile talep gönderdiğinde aynı prosedür devam eder. Tekrar HTTPS'e yönlendirme cevabı göndeririz, istemci tekrar HTTPS ile talepte bulunur, vs. En kötü durumda istemcinin sunucumuzla yaptığı iletişimin %50'si güvenli olmayan HTTP protokolü üzerinden olacaktır. Bu güvenlik riski oluşturabilir.

HTTPS Strict Transport Security (HSTS) protokolü bu riski ortadan kaldırmak için tasarlanmıştır. HSTS protokolü her tarayıcı talebine verilen cevabın "bu hosta talep gönderirken yalnızca HTTPS kullan" anlamına gelen bir header içermesini sağlar. Bu aşamadan sonra aynı tarayıcının aynı hosta gönderdiği diğer bütün talepler HTTPS protokolü üzerinden yapılır. Diğer bir deyişle ilk request dışındaki diğer bütün request'lerde HTTP-HTTPS dönüşümlerini tarayıcı yapar. Örnek (Program.cs dosyası):

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHsts(opts => {
    opts.MaxAge = TimeSpan.FromDays(1);
    opts.IncludeSubDomains = true;
});
var app = builder.Build();
if (app.Environment.IsProduction())
{
    app.UseHsts();
}
app.UseHttpsRedirection();

app.MapFallback(async context => {
    await context.Response.WriteAsync($"HTTPS Request: {context.Request.IsHttps} \n");
    await context.Response.WriteAsync("Hello World!");
});
app.Run();

UseHsts() middleware'i UseHttpsRedirection() middleware'iyle beraber kullanılabilir. Ancak ilk request dışındaki diğer request'lerde UseHttpsRedirection() middleware'ine iş düşmeyecektir. Örnek kodumuzda UseHsts() middleware'i options pattern'iyle konfigüre edilmektedir. UseHsts() middleware'inin ayar sınıfı HstsOptions'tır ve aşağıdaki özellikleri içerir:

ExcludedHosts: Bu hostlara HSTS header'ı gönderilmez. Varsayılanında localhost ve IPv4 ve IPv6'nın loopback adresleri vardır.
IncludeSubDomains: Sunucunun subdomain'lerine yapılan taleplere verilen cevaplarda da HSTS başlığı olup olmayacağını belirtir. Varsayılanı false'tur.
MaxAge: Tarayıcının ne kadar süre boyunca HTTP'den HTTPS'e dönüşüm yapması gerektiğini belirtir. Varsayılanı 30 gündür.
Preload: Sunucuya ilk request'te bile HTTP ile talep gönderilememesini amaçlar. Tarayıcılar HSTS preload şemasındaki domain'lere talepleri mutlaka HTTPS üzerinden yaparlar. Tabii bunun için söz konusu domain'lerin tarayıcılara kodlanması gerekir. Örneğin wikipedia.org domain'i bu şemada bulunmaktadır. Dolayısıyla hiç kimse wikipedia.org adresine HTTP ile talep gönderemez, HTTP talepleri tarayıcıda HTTPS'e dönüştürülüp öyle Wikipedia sunucusuna gönderilir. Herhangi bir domain'in bu şemaya girmesinin uygun olup olmadığına https://hstspreload.org/ adresinden bakabilirsiniz. Ayrıca söz konusu site şemaya girmek için gerekli şartlar ve tavsiyeleri de içerir.

HSTS dikkatli kullanılmalıdır, HTTP ve HTTPS protokolleri için varsayılan portlar kullanılmadığında sorunlar çıkabilir. Örneğin sunucumuzun domain'i host.com olsun ve HTTP için 5000, HTTPS içinse 5500 portunu dinlediğini varsayalım. Kullanıcı ilk talebini HTTP protokolü üzerinden http://host.com:5000 URL'sine yapsın. Bu aşamada sunucu içinde HSTS header'ı olan bir cevapla geri döner. Tarayıcı aynı sunucuya tekrar istek göndereceği zaman HTTP şeklinde olan URL'yi HTTPS'e dönüştürür. Ancak bazı tarayıcılar basit yolu izlerler ve sadece HTTP'yi HTTPS'e çevirip, portta değişiklik yapmadan yeniden talepte bulunurlar. Sunucu hem HTTP'yi hem de HTTPS'i aynı portta dinleyemediği için istemci talebine cevap veremez. Çözüm uygulama canlıya geçtiğinde HTTP ve HTTPS için varsayılan portları kullanmaktadır. HTTP için varsayılan port 80, HTTPS için 443'tür. HTTP ve HTTPS için varsayılan portlar kullanıldığında istemcinin sunucuya talep göndermesi için port belirtimi yapmasına gerek kalmaz.