ASP.NET Web API'sinde Temel Kimlik Doğrulaması

Tarafından Mike Wasson

Temel kimlik doğrulaması RFC 2617, HTTP Kimlik Doğrulaması: Temel ve Özet Erişim Kimlik Doğrulaması'nda tanımlanır.

Dezavantajlar

  • İstekte kullanıcı kimlik bilgileri gönderilir.
  • Kimlik bilgileri düz metin olarak gönderilir.
  • Kimlik bilgileri her istekle birlikte gönderilir.
  • Tarayıcı oturumunu sonlandırma dışında oturumu kapatmanın hiçbir yolu yoktur.
  • Siteler arası istek sahteciliğe (CSRF) karşı savunmasız; CSRF önleme önlemleri gerektirir.

Avantajlar

  • İnternet standardı.
  • Tüm ana tarayıcılar tarafından desteklenir.
  • Görece basit protokol.

Temel kimlik doğrulaması aşağıdaki gibi çalışır:

  1. bir istek kimlik doğrulaması gerektiriyorsa, sunucu 401 (Yetkisiz) döndürür. Yanıt, sunucunun Temel kimlik doğrulamasını desteklediğini belirten bir WWW-Authenticate üst bilgisi içerir.
  2. İstemci, Yetkilendirme üst bilgisinde istemci kimlik bilgileriyle birlikte başka bir istek gönderir. Kimlik bilgileri base64 kodlu "name:password" dizesi olarak biçimlendirilir. Kimlik bilgileri şifrelenmez.

Temel kimlik doğrulaması bir "bölge" bağlamında gerçekleştirilir. Sunucu, WWW-Authenticate üst bilgisinde bölge adını içerir. Kullanıcının kimlik bilgileri bu bölge içinde geçerlidir. Bir alemin tam kapsamı sunucu tarafından tanımlanır. Örneğin, kaynakları bölümlendirmek için birkaç bölge tanımlayabilirsiniz.

Temel kimlik doğrulaması diyagramı

Kimlik bilgileri şifrelenmemiş olarak gönderildiğinden, Temel kimlik doğrulaması yalnızca HTTPS üzerinden güvenlidir. Bkz . Web API'sinde SSL ile Çalışma.

Temel kimlik doğrulaması CSRF saldırılarına karşı da savunmasızdır. Kullanıcı kimlik bilgilerini girdikten sonra, tarayıcı bunları oturum süresi boyunca sonraki isteklerde otomatik olarak aynı etki alanına gönderir. Buna AJAX istekleri dahildir. Bkz . Siteler Arası İstek Sahteciliği (CSRF) Saldırılarını Önleme.

IIS ile Temel Kimlik Doğrulaması

IIS Temel kimlik doğrulamasını destekler, ancak bir uyarı vardır: Kullanıcının Kimliği Windows kimlik bilgileriyle doğrulanır. Bu, kullanıcının sunucunun etki alanında bir hesabı olması gerektiği anlamına gelir. Genel kullanıma yönelik bir web sitesi için genellikle bir ASP.NET üyelik sağlayıcısında kimlik doğrulaması yapmak istersiniz.

IIS kullanarak Temel kimlik doğrulamasını etkinleştirmek için, ASP.NET projenizin Web.config kimlik doğrulama modunu "Windows" olarak ayarlayın:

<system.web>
    <authentication mode="Windows" />
</system.web>

Bu modda IIS, kimlik doğrulaması için Windows kimlik bilgilerini kullanır. Ayrıca, IIS'de Temel kimlik doğrulamasını etkinleştirmeniz gerekir. IIS Yöneticisi'nde Özellikler Görünümü'ne gidin, Kimlik Doğrulaması'nı seçin ve Temel kimlik doğrulamasını etkinleştirin.

I I S Manager panosunun resmi

Web API projenizde, kimlik doğrulaması gerektiren denetleyici eylemleri için özniteliğini ekleyin [Authorize] .

İstemci, istekteki Yetkilendirme üst bilgisini ayarlayarak kimliğini doğrular. Tarayıcı istemcileri bu adımı otomatik olarak gerçekleştirir. Nonbrowser istemcilerinin üst bilgiyi ayarlaması gerekir.

Özel Üyelik ile Temel Kimlik Doğrulaması

Belirtildiği gibi, IIS'de yerleşik olarak bulunan Temel Kimlik Doğrulaması, Windows kimlik bilgilerini kullanır. Bu, barındırma sunucusunda kullanıcılarınız için hesap oluşturmanız gerektiği anlamına gelir. Ancak bir İnternet uygulaması için kullanıcı hesapları genellikle bir dış veritabanında depolanır.

Aşağıdaki kod, Temel Kimlik Doğrulaması gerçekleştiren bir HTTP modülünün nasıl yapıldığını gösterir. Bu örnekteki sahte bir yöntem olan yöntemini değiştirerek CheckPassword ASP.NET üyelik sağlayıcısını kolayca takabilirsiniz.

Web API 2'de, HTTP modülü yerine bir kimlik doğrulama filtresi veya OWIN ara yazılımı yazmayı göz önünde bulundurmalısınız.

namespace WebHostBasicAuth.Modules
{
    public class BasicAuthHttpModule : IHttpModule
    {
        private const string Realm = "My Realm";

        public void Init(HttpApplication context)
        {
            // Register event handlers
            context.AuthenticateRequest += OnApplicationAuthenticateRequest;
            context.EndRequest += OnApplicationEndRequest;
        }

        private static void SetPrincipal(IPrincipal principal)
        {
            Thread.CurrentPrincipal = principal;
            if (HttpContext.Current != null)
            {
                HttpContext.Current.User = principal;
            }
        }

        // TODO: Here is where you would validate the username and password.
        private static bool CheckPassword(string username, string password)
        {
            return username == "user" && password == "password";
        }

        private static void AuthenticateUser(string credentials)
        {
            try
            {
                var encoding = Encoding.GetEncoding("iso-8859-1");
                credentials = encoding.GetString(Convert.FromBase64String(credentials));

                int separator = credentials.IndexOf(':');
                string name = credentials.Substring(0, separator);
                string password = credentials.Substring(separator + 1);

                if (CheckPassword(name, password))
                {
                    var identity = new GenericIdentity(name);
                    SetPrincipal(new GenericPrincipal(identity, null));
                }
                else
                {
                    // Invalid username or password.
                    HttpContext.Current.Response.StatusCode = 401;
                }
            }
            catch (FormatException)
            {
                // Credentials were not formatted correctly.
                HttpContext.Current.Response.StatusCode = 401;
            }
        }

        private static void OnApplicationAuthenticateRequest(object sender, EventArgs e)
        {
            var request = HttpContext.Current.Request;
            var authHeader = request.Headers["Authorization"];
            if (authHeader != null)
            {
                var authHeaderVal = AuthenticationHeaderValue.Parse(authHeader);

                // RFC 2617 sec 1.2, "scheme" name is case-insensitive
                if (authHeaderVal.Scheme.Equals("basic",
                        StringComparison.OrdinalIgnoreCase) &&
                    authHeaderVal.Parameter != null)
                {
                    AuthenticateUser(authHeaderVal.Parameter);
                }
            }
        }

        // If the request was unauthorized, add the WWW-Authenticate header 
        // to the response.
        private static void OnApplicationEndRequest(object sender, EventArgs e)
        {
            var response = HttpContext.Current.Response;
            if (response.StatusCode == 401)
            {
                response.Headers.Add("WWW-Authenticate",
                    string.Format("Basic realm=\"{0}\"", Realm));
            }
        }

        public void Dispose() 
        {
        }
    }
}

HTTP modülünü etkinleştirmek için system.webServer bölümündeki web.config dosyanıza aşağıdakileri ekleyin:

<system.webServer>
    <modules>
      <add name="BasicAuthHttpModule" 
        type="WebHostBasicAuth.Modules.BasicAuthHttpModule, YourAssemblyName"/>
    </modules>

"YourAssemblyName" ifadesini derlemenin adıyla değiştirin ("dll" uzantısı dahil değildir).

Forms veya Windows kimlik doğrulaması gibi diğer kimlik doğrulama düzenlerini devre dışı bırakmanız gerekir.