Bagikan melalui


Autentikasi Dasar di API Web ASP.NET

oleh Mike Wasson

Autentikasi dasar ditentukan dalam RFC 2617, Autentikasi HTTP: Autentikasi Akses Dasar dan Hash.

Kekurangan

  • Kredensial pengguna dikirim dalam permintaan.
  • Kredensial dikirim sebagai teks biasa.
  • Kredensial dikirim dengan setiap permintaan.
  • Tidak ada cara untuk keluar, kecuali dengan mengakhiri sesi browser.
  • Rentan terhadap pemalsuan permintaan lintas situs (CSRF); membutuhkan langkah-langkah anti-CSRF.

Kelebihan

  • Standar internet.
  • Didukung oleh semua browser utama.
  • Protokol yang relatif sederhana.

Autentikasi dasar berfungsi sebagai berikut:

  1. Jika permintaan memerlukan autentikasi, server mengembalikan 401 (Tidak Sah). Respons mencakup header WWW-Authenticate, yang menunjukkan server mendukung autentikasi Dasar.
  2. Klien mengirim permintaan lain, dengan kredensial klien di header Otorisasi. Kredensial diformat sebagai string "name:password", base64-encoded. Kredensial tidak dienkripsi.

Autentikasi dasar dilakukan dalam konteks "realm." Server menyertakan nama realm di header WWW-Authenticate. Kredensial pengguna valid dalam realm tersebut. Cakupan realm yang tepat ditentukan oleh server. Misalnya, Anda dapat menentukan beberapa realm untuk mempartisi sumber daya.

Diagram autentikasi dasar

Karena kredensial dikirim tidak terenkripsi, autentikasi Dasar hanya aman melalui HTTPS. Lihat Bekerja dengan SSL di API Web.

Autentikasi dasar juga rentan terhadap serangan CSRF. Setelah pengguna memasukkan kredensial, browser secara otomatis mengirimkannya pada permintaan berikutnya ke domain yang sama, selama durasi sesi. Ini termasuk permintaan AJAX. Lihat Mencegah Serangan Pemalsuan Permintaan Lintas Situs (CSRF).

Autentikasi Dasar dengan IIS

IIS mendukung autentikasi Dasar, tetapi ada peringatan: Pengguna diautentikasi terhadap kredensial Windows mereka. Itu berarti pengguna harus memiliki akun di domain server. Untuk situs web yang menghadap publik, Anda biasanya ingin mengautentikasi terhadap penyedia keanggotaan ASP.NET.

Untuk mengaktifkan autentikasi Dasar menggunakan IIS, atur mode autentikasi ke "Windows" di Web.config proyek ASP.NET Anda:

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

Dalam mode ini, IIS menggunakan kredensial Windows untuk mengautentikasi. Selain itu, Anda harus mengaktifkan autentikasi Dasar di IIS. Di Manajer IIS, buka Tampilan Fitur, pilih Autentikasi, dan aktifkan Autentikasi dasar.

Gambar dasbor I I S Manager

Di proyek Web API Anda, tambahkan [Authorize] atribut untuk tindakan pengontrol apa pun yang memerlukan autentikasi.

Klien mengautentikasi dirinya sendiri dengan mengatur header Otorisasi dalam permintaan. Klien browser melakukan langkah ini secara otomatis. Klien nonbrowser harus mengatur header.

Autentikasi Dasar dengan Keanggotaan Kustom

Seperti disebutkan, Autentikasi Dasar yang disertakan dalam IIS menggunakan kredensial Windows. Itu berarti Anda perlu membuat akun untuk pengguna Anda di server hosting. Tetapi untuk aplikasi internet, akun pengguna biasanya disimpan dalam database eksternal.

Kode berikut bagaimana modul HTTP yang melakukan Autentikasi Dasar. Anda dapat dengan mudah mencolokkan penyedia keanggotaan ASP.NET dengan mengganti CheckPassword metode , yang merupakan metode dummy dalam contoh ini.

Di Web API 2, Anda harus mempertimbangkan untuk menulis filter autentikasi atau middleware OWIN, bukan modul HTTP.

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() 
        {
        }
    }
}

Untuk mengaktifkan modul HTTP, tambahkan yang berikut ini ke file web.config Anda di bagian system.webServer :

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

Ganti "YourAssemblyName" dengan nama assembly (tidak termasuk ekstensi "dll").

Anda harus menonaktifkan skema autentikasi lainnya, seperti Formulir atau autentikasi Windows.