Asegurar la API web de ASP.NET

Una vez que haya desarrollado su API web, antes de exponerla a sus clientes, en función de sus necesidades, es posible que deba proteger algunas o todas las partes de su servicio API para que solo los usuarios verificados puedan acceder a su servicio API. Esta protección en ASP.NET se puede lograr mediante los mecanismos de autenticación y autorización..

Autenticación

La autenticación es el proceso de determinar si alguien o algo es, de hecho, quién o qué se dice que es. Al utilizar el mecanismo de autenticación, nos aseguramos de que todas las solicitudes recibidas por el servicio de API web se envíen desde un cliente con las credenciales adecuadas..

Autenticación mediante manejadores de mensajes

UNA manejador de mensajes es una clase que recibe una solicitud HTTP y devuelve una respuesta HTTP. Los manejadores de mensajes son clases derivadas de la clase abstracta. HttpMessageHandler. Son buenos para las preocupaciones transversales que operan en el nivel de los mensajes HTTP (en lugar de las acciones del controlador). Por ejemplo, un manejador de mensajes podría:

  • leer o modificar los encabezados de solicitud
  • agregar un encabezado de respuesta a las respuestas
  • validar las solicitudes antes de que lleguen al controlador

En una API web, normalmente, una serie de manejadores de mensajes se encadenan formando un patrón llamado delegar entrenador de animales.

El orden en que se configuran estos controladores es importante ya que se ejecutarán secuencialmente. 

El controlador más importante se encuentra en la parte superior, protegiendo todo lo que entra. Si las comprobaciones pasan, pasará esta solicitud por la cadena al siguiente controlador de delegación, y así sucesivamente.. 

Si todo va bien, llegará al Controlador de API y ejecutará la acción deseada. Sin embargo, si alguna de las comprobaciones falla dentro de los controladores, la solicitud se deniega y se envía una respuesta al cliente..

Con toda esta teoría en la mano, ahora escribamos código para nuestros manejadores. Crearemos dos manejadores de mensajes en este artículo:

  1. APIKeyHandler: Manejador responsable de interceptar una solicitud HTTP y asegurar que su encabezado contenga una clave API
  2. AuthHandler: Controlador responsable de autenticar las credenciales y roles de un usuario

Autenticación de clave API

En su proyecto de API web, cree una carpeta llamada Manejadores de mensajesy añadir una clase APIKeyHandler.cs.

clase pública APIKeyHandler: DelegatingHandler // establezca una clave privada de API predeterminada const string yourApiKey = "X-some-key"; anulación protegida tarea asíncrona SendAsync (solicitud HttpRequestMessage, Cancelación de cancelación cancelada) (bool isValidAPIKey = false; Enumerable lsheaders; // Valide que exista la clave api var checkApiKeyExists = request.Headers.TryGetValues ​​("API_KEY", out lsHeaders); if (checkApiKeyExists) if (lsHeaders.FirstOrDefault (). Equals (yourApiKey)) isValidAPIKey = true;  // Si la clave no es válida, devuelva un código de estado http. if (! isValidAPIKey) return request.CreateResponse (HttpStatusCode.Forbidden, "Bad API Key"); // Permitir que la solicitud procese más abajo en la canalización var response = await base.SendAsync (request, cancelaciónToken); // Devuelve la respuesta una copia de seguridad de la cadena de respuesta; 

los APIKeyHandler.cs hereda de Delegando a handler, que a su vez hereda de HttpMessageHandler. Esto nos permite anular la funcionalidad para inspeccionar una solicitud HTTP y controlar si queremos permitir que esta solicitud fluya por la tubería hacia el siguiente controlador y controlador o detener la solicitud mediante el envío de una respuesta personalizada.

En esta clase, lo estamos logrando anulando el SendAsync método. Este método busca una clave API (CLAVE API) en el encabezado de cada solicitud HTTP, y pasa la solicitud al controlador solo si hay una clave de API válida en el encabezado de la solicitud.

Ahora, para ver este controlador en acción, primero debemos registrarlo en nuestra aplicación en el Inicio de aplicación método de la Global.asax expediente.

GlobalConfiguration.Configuration.MessageHandlers.Add (new APIKeyHandler ());

Intente llamar a cualquier método que haya expuesto a través de sus controladores de API web y debería ver "Clave de API incorrecta" como respuesta.

Para una demostración de este artículo, estoy usando el mismo proyecto y las URL que he creado en mi artículo anterior, "Desarrollo de una API web ASP.NET".

Vamos a verificar que la APIKeyHandlerestá funcionando bien creando una solicitud HTTP con los encabezados correctos. Para eso, necesitamos crear un encabezado HTTP con valor clave:

"API_KEY": "X-some-key"

Estoy usando un complemento del navegador Mozilla llamado "Herramienta HTTP" para crear encabezados de solicitud HTTP aquí.

La solicitud HTTP se pasa ahora al controlador por el controlador.

Así que nuestro manejador de verificación de clave API está en su lugar ahora. Esto protege nuestra API web para garantizar que solo aquellos clientes que cuentan con claves de API válidas puedan acceder a este servicio. A continuación veremos cómo podemos implementar la seguridad basada en roles de usuario..

Autenticación básica

La autenticación básica, como su nombre lo indica, es la forma más simple y básica de autenticar solicitudes HTTP. El cliente envía credenciales codificadas en Base64 en el encabezado Autorizar en cada solicitud HTTP, y solo si las credenciales son verificadas, la API devuelve la respuesta esperada. La autenticación básica no requiere el almacenamiento de sesión del lado del servidor ni la implementación de cookies, ya que cada solicitud es verificada por la API.

Una vez que se entienda la implementación de la autenticación básica en la API web, será muy fácil conectar otras formas de autenticación. Solo el proceso de autenticación será diferente, y los enlaces de la API web, donde se realiza, serán los mismos.

Para verificar las credenciales de los usuarios, creamos un IPrincipal objeto que representa el contexto de seguridad actual.

Añadir una nueva carpeta llamada Seguridad y una nueva clase TestAPIPrincipal.cs en eso.

clase pública TestAPIPrincipal: IPrincipal // Constructor public TestAPIPrincipal (string userName) UserName = userName; Identidad = nueva GenericIdentity (nombre de usuario);  cadena pública Nombre de usuario obtener; conjunto;  identidad de identidad pública obtener; conjunto;  public bool IsInRole (string role) if (role.Equals ("usuario")) return true;  else devolver falso; 

los Identidad objeto asociado con el principal tiene una propiedad llamada Es autenticado. Si el usuario está autenticado, esta propiedad devolverá true; De lo contrario, devolverá falso..

Ahora, vamos a crear otro controlador llamado AuthHandler.cs.

clase pública AuthHandler: DelegatingHandler string _userName = ""; // Método para validar las credenciales de Autorización // valor de cabecera private bool ValidateCredentials (AuthenticationHeaderValue authenticationHeaderVal) try if (authenticationHeaderVal! = Null &&! String.IlucesValores.com) (Convert.FromBase64String (authenticationHeaderVal.Parameter)) .Split (new [] ':'); // ahora decodedCredentials [0] contendrá // nombre de usuario y decodedCredentials [1] // contendrá la contraseña. if (decodedCredentials [0] .Equals ("username") && decodedCredentials [1] .Equals ("password")) _userName = "John Doe"; devolver verdadero; // solicitud autenticada.  devolver falso; // solicitud no autenticada.  catch return false;  Proteger anular Async Tarea SendAsync (solicitud HttpRequestMessage, CancelaciónToken cancelaciónToken) // si se validan las credenciales, // establece CurrentPrincipal y Current.User if (ValidateCredentials (request.Headers.Authorization)) Thread.CurrentPrincipal = new TestAPIPrincipal (_NameName))! HttpContext.Current.User = new TestAPIPrincipal (_userName);  // Ejecutar base.SendAsync para ejecutar // acciones predeterminadas y una vez que se complete, // capturar el objeto de respuesta y agregar // WWW-Autenticar encabezado si la solicitud // se marcó como no autorizada. // Permitir que la solicitud procese más abajo en la canalización var response = await base.SendAsync (request, cancelaciónToken); if (response.StatusCode == HttpStatusCode.Unauthorized &&! response.Headers.Contains ("WwwAuthenticate")) response.Headers.Add ("WwwAuthenticate", "Basic"); respuesta de retorno; 

Esta clase contiene un método privado. ValidateCredentials, que comprueba los valores de nombre de usuario y contraseña decodificados desde el encabezado de solicitud HTTP, y también la SendAsyncMétodo para interceptar la solicitud HTTP..

Si las credenciales del cliente son válidas, entonces la actual IPrincipalobjeto se adjunta al hilo actual, es decir,. Thread.CurrentPrincipal. También establecemos el HttpContext.Current.User hacer que el contexto de seguridad sea consistente. Esto nos permite acceder a los detalles del usuario actual desde cualquier lugar de la aplicación..

Una vez autenticada la solicitud., base.SendAsync Se llama para enviar la solicitud al manejador interno. Si la respuesta contiene un encabezado HTTP no autorizado, el código inyecta un Autenticación de Www encabezado con el valor BASICInformar al cliente que nuestro servicio espera autenticación básica..

Ahora, necesitamos registrar este controlador en el Global.Asax clase como lo hicimos para nuestro ApiKeyHandler. Asegúrese de que el AuthHandlerel manejador está por debajo del primer registro de manejador para asegurarse del orden correcto.

GlobalConfiguration.Configuration.MessageHandlers.Add (new APIKeyHandler ()); GlobalConfiguration.Configuration.MessageHandlers.Add (new AuthHandler ());

Pero antes de que podamos ver la autenticación básica en acción, primero necesitaremos implementar la autorización..

Autorización

La autorización es verificar si el usuario autenticado puede realizar una acción en particular o consumir un recurso en particular. Este proceso en la API web ocurre más adelante en la tubería, después de
Autenticación y antes de que se ejecuten las acciones del controlador..

Usando el atributo de autorización

ASP.NET MVC Web API proporciona un filtro de autorización llamado AutorizarAtributoque verifica la solicitud IPrincipal, comprueba su Identity.IsAuthenticated propiedad, y devuelve un 401 no autorizado Estado HTTP si el valor es falso y el método de acción solicitado no se ejecutará. Este filtro se puede aplicar en diferentes niveles, como el nivel del controlador o el nivel de acción, y se puede aplicar fácilmente usando el [Autorizar]sintaxis sobre controladores o acciones.

[Autorizar] clase pública ClassifiedsController: ApiController

Una vez que se establece este atributo, evitará que usuarios no autorizados accedan a todos los métodos de acción en el controlador.

Primero se inicia nuestro controlador de autenticación básico para establecer la identidad del usuario actual IPrincipal objeto. Luego, antes de que esta solicitud llegue al controlador., AutorizarAtributo verifica el acceso al controlador / acción particular para el usuario actual.

Para ver esto en acción, primero creamos una solicitud HTTP sin las credenciales adecuadas.

El acceso es denegado por la AutorizarAtributo.

Ahora, vamos a crear otra solicitud con clave / valor de encabezado de autorización esta vez de la siguiente manera:

Autorización: Basic dXNlcm5hbWU6cGFzc3dvcmQ =

Aquí, el valor dXNlcm5hbWU6cGFzc3dvcmQ =es elBase codificada en forma de 64 usuario Contraseña.

Esta solicitud obtiene los derechos de acceso al controlador / acción como se esperaba..

Este es un ejemplo de cómo asegurar las acciones públicas de todo el controlador..

Autorización de Nivel de Acción

También podemos restringir algunas partes de las acciones del controlador configurando el[Autorizar] atributo en el nivel de acción sólo en su lugar. Si lo hace, nos permitirá tener acciones tanto protegidas como no protegidas en el mismo controlador.

// [Autorizar] clase pública ClassifiedsController: ApiController lista pública Get (string id) return ClassifiedService.GetClassifieds (id);  [Autorizar] Lista pública Get () return ClassifiedService.GetClassifieds (""); 

Atributo [AllowAnonymous]

Otra forma de tener acciones tanto protegidas como no protegidas dentro del controlador es haciendo uso de la [Permitir anónimos] atributo. Cuando configuramos el [Autorizar] atributo en el nivel de controlador y establecer el [Permitir anónimos] atributo para cualquier acción dentro del controlador, esa acción saltará la [Autorizar] atributo.

Control de roles y usuarios

También es posible filtrar ciertos roles y usuarios para los derechos de acceso. Por ejemplo, podemos tener algo como [Autorizar (Roles = "Admin")] En los controladores y acciones..

Atributo de autorización personalizada

Finalmente, también podemos crear nuestro propio atributo de autorización personalizado según nuestras necesidades. Una de las maneras de lograr esto es extendiendo AutorizarAtributo.

Supongamos que queremos restringir nuestro servicio de API web solo a ciertas partes del mundo restringiendo el acceso a los usuarios que no están dentro de un cierto rango de direcciones IP. Podemos crear un atributo de autorización personalizado para este propósito derivando del AutorizarAtributoclase y anulando el Está autorizado método.

clase pública RestrictIPsAttribute: System.Web.Http.AuthorizeAttribute protegido anulación bool IsAuthorized (HttpActionContext context) var ip = HttpContext.Current.Request.UserHostAddress; // compruebe si hay ip aquí si (ip.Contains ("")) return true;  falso retorno; 

Una vez que tengamos nuestro atributo Autorizar personalizado, podemos decorar nuestros controladores / acciones con él.

[RestrictIPsAttribute] lista pública Get () return ClassifiedService.GetClassifieds (""); 

Conclusión

En este artículo, analizamos cómo podemos asegurar nuestro servicio de API web ASP.NET antes de exponer el servicio al mundo exterior. Analizamos cómo podemos autenticar solicitudes HTTP para claves de API válidas y para credenciales de usuario válidas. Con todo este conocimiento en la mano, creo que estamos listos para desarrollar cualquier seguridad personalizada para nuestras API.

Para aquellos de ustedes que ya están comenzando con Laravel o que desean ampliar sus conocimientos, sitio o aplicación con extensiones, tenemos una variedad de cosas que puede estudiar en Envato Market..

Espero que haya disfrutado tanto leyendo como aprendiendo de este artículo, y recuerde dejar cualquier pregunta o comentario en la siguiente información.!