Yazılım Mimarileri ve Tasarım Desenleri Üzerine

Asp.NET Core’da Current User’ı Elde Etmek

Merhaba,

Asp.NET Core ile geliştirdiğimiz uygulamaların çoğunda authentication ve authorization yaygın olarak kullandığımız güvenlik protokolleridir. Genellikle, bu protokoller neticesinde doğrulanan kullanıcıların bilgilerine erişim gösterebildikleri noktalarda bizler tarafından ihtiyaç duyulabilmektedir. Bu konuya dair kaynakları taradığımızda kimi uygulamalarda kullanıcı bilgisi için identity provider’la etkileşim kurulduğunu görmekteyiz. Halbuki her kullanıcı bilgisi ihtiyacına karşın bu davranışın hem maliyetli hem de mimarisel olarak ilke dışı bir yöntem olduğunu söyleyebiliriz. Burada yapılması gereken claim tabanlı kullanıcı bilgisinin client’a aktarılması ve ihtiyaç noktalarında bu bilgilerin claim üzerinden elde edilmesidir. Tabi bunun için de bir soyutlama çalışması elzemdir. İşte bu içeriğimizde bu basit ama etkili yöntemi teknik olarak değerlendiriyor olacağız. Buyurun başlayalım…

İlk olarak aşağıdaki gibi bir abstraction yapısı oluşturarak başlayalım;

    public interface IUserContext
    {
        bool IsAuthenticated { get; }
        Guid UserId { get; }
        string Username { get; }
    }

Burada mevcut kullanıcıya dair ihtiyacımız olan bilgileri tutuyoruz. Tabi ki de gerekli olduğu düşünülen farklı veriler söz konusuysa eğer bunları da ekleyerek bu interface genişletilebilir. Şimdi bu abstraction’ı bir concrete class’a uygulayarak mevcut kullanıcının claim’lerini içeren ClaimsPrincipal‘a erişelim. Tabi bunun için de aşağıdaki gibi extension metot’lardan istifade edeceğiz.

    public static class ClaimsPrincipalExtensions
    {
        public static Guid GetUserId(this ClaimsPrincipal? claimsPrincipal)
        {
            string? userId = claimsPrincipal?.FindFirstValue("UserId");
            return Guid.TryParse(userId, out Guid parsedUserId) ? parsedUserId : throw new ApplicationException();
        }

        public static string GetUsername(this ClaimsPrincipal? claimsPrincipal)
        {
            string? username = claimsPrincipal?.FindFirstValue(ClaimTypes.NameIdentifier);
            return username;
        }
    }

Ve concrete class’ı oluşturup, implementasyonu gerçekleştirelim.

    public sealed class UserContext(IHttpContextAccessor httpContextAccessor) : IUserContext
    {
        public bool IsAuthenticated =>
            httpContextAccessor
            .HttpContext?
            .User
            .Identity?
            .IsAuthenticated ?? false;

        public Guid UserId =>
            httpContextAccessor
            .HttpContext?
            .User
            .GetUserId() ?? throw new ApplicationException();

        public string Username =>
            httpContextAccessor
            .HttpContext?
            .User
            .GetUsername() ?? throw new ApplicationException();
    }

Ve bu işlemin ardından aşağıdaki gibi IoC Container tanımlamasında bulunduktan sonra mevcut kullanıcı bilgilerine istediğimiz noktadan erişim gösterebiliriz.

builder.Services.AddSingleton<IUserContext, UserContext>();

Şöyle ki;

app.MapGet("/get-userid", (IUserContext userContext) => userContext.UserId)
    .RequireAuthorization();

app.MapGet("/get-username", (IUserContext userContext) => userContext.Username)
    .RequireAuthorization();

Tabi buradaki örneğin dışında mevcut kullanıcı bilgilerine onion architecture gibi profesyonel mimarilerin application katmanlarından ya da CQRS pattern davranışının uygulandığı handle sınıflarından rahatlıkla erişim gösterebilir ve etkin bir şekilde yönetebiliriz.

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Not : Örnek çalışmaya aşağıdaki github adresinden erişebilirsiniz.
https://github.com/gncyyldz/Get.Current.User.Example

Exit mobile version