Implementieren Sie die HTTP-Authentifizierung in der Web-API

In diesem Artikel möchte ich eine Diskussion zur Implementierung der HTTP-Authentifizierung in der Web-API vorstellen. Es gibt zwei Möglichkeiten, wie Sie die HTTP-Authentifizierung in Ihrer Web-API implementieren können. Diese schließen ein:

  • Formularauthentifizierung
  • Grundlegende Authentifizierung

Wir würden die Windows-Authentifizierung nicht als praktikable Strategie betrachten, da Sie Ihren Dienst nicht über das Internet verfügbar machen können, wenn Sie die Windows-Authentifizierung nutzen.

Sichern der Web-API mithilfe der Formularauthentifizierung

Die Formularauthentifizierung verwendet den ASP.Net-Mitgliedschaftsanbieter und verwendet anstelle des Autorisierungsheaders Standard-HTTP-Cookies. Die Formularauthentifizierung ist nicht so REST-freundlich, da Cookies verwendet werden. Die Clients müssten Cookies verwalten, um Dienste zu nutzen, die die Formularauthentifizierung nutzen, die für standortübergreifende Fälschungsangriffe anfällig ist. Aus diesem Grund müssten Sie CSRF-Maßnahmen implementieren, wenn Sie die Formularauthentifizierung verwenden. Die Formularauthentifizierung verwendet keine Verschlüsselung, um die Anmeldeinformationen des Benutzers zu sichern. Daher ist dies keine sichere Strategie, es sei denn, Sie führen Ihre Web-API über SSL aus.

Sichere Web-API mithilfe der Basisauthentifizierung

Bei der Standardauthentifizierung werden die Anmeldeinformationen des Benutzers im Klagetext über die Leitung gesendet. Wenn Sie die Basisauthentifizierung verwenden möchten, sollten Sie Ihre Web-API über eine SSL (Secure Socket Layer) verwenden. Bei Verwendung der Basisauthentifizierung übergeben wir die Anmeldeinformationen des Benutzers oder das Authentifizierungstoken im Header der HTTP-Anforderung. Der Dienst auf der Serverseite müsste den Header analysieren, um das Authentifizierungstoken abzurufen. Wenn die Anforderung keine gültige Anforderung ist, gibt der Server HTTP 401 zurück, was eine nicht autorisierte Antwort bedeutet.

Lassen Sie uns untersuchen, wie wir eine grundlegende Authentifizierung mithilfe eines Aktionsfilters durchführen können. Dazu sollten Sie eine Klasse erstellen, die die System.Web.Http.Filters.ActionFilterAttributeKlasse wie folgt ableitet :

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);

            }

        }

    }

Wir prüfen, ob der Autorisierungsheader vorhanden ist. Andernfalls wird eine HTTP 401- oder "nicht autorisierte" Antwort zurückgegeben.

Der nächste Schritt besteht darin, die Benutzeranmeldeinformationen zu überprüfen, die über den Autorisierungsanforderungsheader vom Client übergeben wurden. Bevor wir das tun, sollten wir wissen, wie die Web-API vom Client aufgerufen werden soll. Dafür habe ich eine Testmethode vorbereitet. Die Testmethode verwendet die HttpClientKlasse, um die Web-API aufzurufen. Beachten Sie, dass die Benutzernamen vor der Übergabe in das Base64-Zeichenfolgenformat konvertiert werden. Die Testmethode ist unten angegeben.

[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);

        }

Wie Sie im obigen Codeausschnitt sehen können, werden die Benutzeranmeldeinformationen mithilfe des Autorisierungsheaders übergeben.

Nachdem der Client bereit ist, schließen wir die Implementierung der BasicAuthenicationFilterKlasse ab. Innerhalb der OnActionExecutingMethode müssten wir den Header-Wert in dieser Klasse analysieren und prüfen, ob die vom Client angegebenen Anmeldeinformationen übereinstimmen. Denn jetzt, nehmen wir an , dass der Benutzername und das Passwort Werte hat joydipund joydip123jeweils (sie sind hart codiert). Hier ist der vollständige Code der BasicAuthenticationFilterKlasse, der die Validierung der Benutzeranmeldeinformationen enthält.

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);

            }

        }

    }

In Ihrer Controller-Klasse sollten Sie das Attribut entsprechend angeben. Beachten Sie, dass sich das BasicAuthenticationAttribut hier auf die von BasicAuthenticationAttributeuns implementierte Klasse bezieht .

    [BasicAuthentication]

    public class DefaultController : ApiController

    {

        public IEnumerable Get()

        {

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

        }

    }

Nun ein bisschen Konfiguration - Sie müssen das Attribut so konfigurieren, dass Aufrufe an Ihren Controller entsprechend gefiltert werden, damit die Authentifizierung funktioniert.

 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());

        }

    }

Und du bist fertig! Wenn Sie den Testfall ausführen, besteht der Test.

Sie sollten trotzdem sicherstellen, dass die Anmeldeinformationen nicht fest codiert sind. Stattdessen sollten sie in einer Datenbank gespeichert werden und Sie sollten sie abrufen und in der OnActionExecutingMethode der BasicAuthenticationAttributeKlasse validieren .