Laksanakan pengesahan HTTP di Web API

Dalam artikel ini saya akan menyampaikan perbincangan mengenai pelaksanaan pengesahan HTTP di API Web. Terdapat dua cara di mana anda dapat melaksanakan pengesahan HTTP di Web Api anda. Ini termasuk:

  • Pengesahan borang
  • Pengesahan asas

Kami tidak akan menganggap pengesahan Windows sebagai strategi yang dapat dilaksanakan kerana anda tidak dapat mendedahkan perkhidmatan anda melalui Internet jika anda menggunakan pengesahan Windows.

Melindungi Web Api menggunakan Formulir Pengesahan

Pengesahan borang menggunakan penyedia keahlian ASP.Net dan menggunakan kuki HTTP standard dan bukan tajuk Pengesahan. Pengesahan borang tidak mesra REST kerana menggunakan kuki, dan pelanggan perlu menguruskan kuki untuk menggunakan perkhidmatan yang memanfaatkan pengesahan bentuk, yang rentan terhadap serangan pemalsuan lintas-laman web. Inilah sebabnya mengapa anda perlu melaksanakan langkah CSRF jika anda menggunakan pengesahan borang. Pengesahan borang tidak menggunakan penyulitan untuk menjamin kelayakan pengguna. Oleh itu, ini bukan strategi yang selamat melainkan anda menjalankan API Web anda melalui SSL.

API Web Selamat menggunakan pengesahan asas

Pengesahan asas menghantar bukti kelayakan pengguna dalam teks biasa melalui wayar. Sekiranya anda menggunakan pengesahan asas, anda harus menggunakan API Web anda melalui Secure Socket Layer (SSL). Semasa menggunakan pengesahan asas, kami akan memberikan bukti kelayakan pengguna atau token pengesahan pada tajuk permintaan HTTP. Perkhidmatan di bahagian pelayan perlu menguraikan tajuk untuk mengambil token pengesahan. Sekiranya permintaan itu bukan permintaan yang sah, pelayan mengembalikan HTTP 401, yang bermaksud respons yang tidak sah.

Mari terokai bagaimana kita dapat melakukan pengesahan asas menggunakan penapis tindakan. Untuk melakukan ini, anda harus membuat kelas yang berasal dari System.Web.Http.Filters.ActionFilterAttributekelas seperti yang ditunjukkan di bawah:

public class BasicAuthenticationAttribute : System.Web.Http.Filters.ActionFilterAttribute

    {

        private Boolean IsUserValid(Dictionary credentials)

        {

            if (credentials["UserName"].Equals("joydip") && credentials["Password"].Equals("joydip123"))

                return true;

            return false;

        }

         private Dictionary ParseRequestHeaders(System.Web.Http.Controllers.HttpActionContext actionContext)

        {

            Dictionary credentials = new Dictionary();

             var httpRequestHeader = actionContext.Request.Headers.GetValues("Authorization").FirstOrDefault();

            httpRequestHeader = httpRequestHeader.Substring("Authorization".Length);

             string[] httpRequestHeaderValues = httpRequestHeader.Split(':');

            string username = Encoding.UTF8.GetString(Convert.FromBase64String(httpRequestHeaderValues[0]));

            string password = Encoding.UTF8.GetString(Convert.FromBase64String(httpRequestHeaderValues[1]));

             credentials.Add("UserName", username);

            credentials.Add("Password", password);

             return credentials;

        }

         public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)

        {

            try

            {

                if (actionContext.Request.Headers.Authorization == null)

                {

                    actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);

                }

                else

                {

                     Dictionary credentials = ParseRequestHeaders(actionContext);

                     if (IsUserValid(credentials))

                        actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.OK);

                    else

                        actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);

                 }

            }

            catch

            {

                actionContext.Response = new System.Net.Http.HttpResponseMessage

(System.Net.HttpStatusCode.InternalServerError);

            }

        }

    }

Kami memeriksa sama ada pengepala kebenaran ada; jika tidak, jawapan HTTP 401 atau "tidak sah" dikembalikan.

Langkah seterusnya adalah mengesahkan kelayakan pengguna yang dilalui melalui tajuk permintaan kebenaran dari klien. Sebelum melakukannya, kita harus mengetahui bagaimana API Web dipanggil dari klien. Untuk ini, saya telah menyediakan kaedah ujian. Kaedah ujian menggunakan HttpClientkelas untuk memanggil API Web. Perhatikan bahawa nama pengguna ditukar ke format rentetan Base64 sebelum dilewatkan. Kaedah ujian diberikan di bawah.

[TestMethod]

        public void BasicAuthenticationTest()

        {

            string username = Convert.ToBase64String(Encoding.UTF8.GetBytes("joydip"));

            string password = Convert.ToBase64String(Encoding.UTF8.GetBytes("joydip123"));

            HttpClient client = new HttpClient();

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Authorization", username + ":" + password);

            var result = client.GetAsync(new Uri("//localhost//api/default/")).Result;

           Assert.IsTrue(result.IsSuccessStatusCode);

        }

Seperti yang anda lihat dalam coretan kod di atas, kelayakan pengguna diluluskan menggunakan tajuk kebenaran.

Setelah pelanggan bersedia, mari selesaikan pelaksanaan BasicAuthenicationFilterkelas. Di dalam OnActionExecutingkaedah ini, kita perlu menguraikan nilai header di kelas ini dan memeriksa apakah kelayakan yang diberikan dari klien sesuai. Buat masa ini, mari kita anggap bahawa nama pengguna dan kata laluan mempunyai nilai joydipdan joydip123, masing-masing (mereka dikodkan keras). Inilah kod lengkap BasicAuthenticationFilterkelas yang menggabungkan pengesahan kelayakan pengguna.

public class BasicAuthenticationAttribute : System.Web.Http.Filters.ActionFilterAttribute

    {

        public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)

        {

            try

            {

                if (actionContext.Request.Headers.Authorization == null)

                {

                    actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);

                }

                else

                {

                    actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError);

                    var httpRequestHeader = actionContext.Request.Headers.GetValues("Authorization").FirstOrDefault();

                    httpRequestHeader = httpRequestHeader.Substring("Authorization".Length);

                    string[] httpRequestHeaderValues = httpRequestHeader.Split(':');

                    string username = Encoding.UTF8.GetString(Convert.FromBase64String(httpRequestHeaderValues[0]));

                    string password = Encoding.UTF8.GetString(Convert.FromBase64String(httpRequestHeaderValues[1]));

                    if (username.Equals("joydip") && password.Equals("joydip123"))

                        actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.OK);

                    else

                        actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);

                }

            }

            catch

            {

                actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError);

            }

        }

    }

Di kelas pengawal anda, anda harus menentukan atribut dengan tepat. Perhatikan bahawa BasicAuthenticationatribut di sini merujuk kepada BasicAuthenticationAttributekelas yang kami laksanakan.

    [BasicAuthentication]

    public class DefaultController : ApiController

    {

        public IEnumerable Get()

        {

            return new string[] { "Joydip", "Kanjilal" };

        }

    }

Sekarang, sedikit konfigurasi --- anda perlu mengkonfigurasi atribut supaya panggilan ke pengawal anda disaring dengan betul agar pengesahan berfungsi.

 public static class WebApiConfig

    {

        public static void Register(HttpConfiguration config)

        {

            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(

                name: "DefaultApi",

                routeTemplate: "api/{controller}/{id}",

                defaults: new { id = RouteParameter.Optional }

            );

            config.Formatters.Remove(config.Formatters.XmlFormatter);

            GlobalConfiguration.Configuration.Filters.Add(new BasicAuthenticationAttribute());

        }

    }

Dan anda sudah selesai! Semasa anda menjalankan kes ujian, ujian itu lulus.

Anda harus memastikan bahawa tauliah tidak dikodkan; sebaliknya, mereka harus disimpan dalam pangkalan data dan anda harus mengambilnya dan mengesahkannya dalam OnActionExecutingkaedah BasicAuthenticationAttributekelas.