Como hacer seguros tus servicios WebApi

Buenas! Este post surge a raíz del comentario de Felix Manuel en mi post anterior Inyección de dependencias per-Request. En él Felix comentaba que le gustaría ver algo sobre autenticación y autorización de WebApi… así que vamos a ello.

Todo lo que comentaré en este post va destinado a servicios WebApi que queramos tener en internet. No hablaré nada de otros escenarios como intranets que pueden tener otras soluciones.

Vamos a partir del template de proyecto ASP.NET MVC4 – WebApi

AuthorizeAttribute

En ASP.NET MVC si queremos añadir seguridad a un controlador, basta con que usemos [Authorize] para decorar todas aquellas acciones que requieran seguridad.

¿Qué ocurre si aplicamos lo mismo a WebApi?

public class SecureController : ApiController

{

    [Authorize]

    public string GetSecure()

    {

        return "Acces granted!";

    }

}

Asegúrate de usar el AuthorizeAttribute que está en System.Web.Http, no el que está en System.Web.Mvc!

Con esto, si realizo una llamada GET a /api/secure obtengo un mensaje de error (recuerda que puedes recibirlo en json o xml dependiendo de la cabecera accept que mandes):

<Error><Message>Authorization has been denied for this request.</Message></Error>

Bien… parece que el filtro realiza su trabajo, pero ¿qué hace exactamente? Para ello echemos un vistazo a su código fuente. El método que realiza el trabajo es IsAuthorized que tiene un código como el siguiente:

IPrincipal user = Thread.CurrentPrincipal;

if (user == null || !user.Identity.IsAuthenticated)

{

    return false;

}

Bueno… pues parece que está claro: [Authorize] se limita a validar que haya un CurrentPrincipal que esté autorizado.

¿Así que la pregunta nos rebota: quien crea y coloca el IPrincipal autorizado?

Para verlo, realicemos una prueba: Vamos a crear un controlador nuevo con un método GET (para llamarlo fácilmente desde el navegador) para autenticarnos, usando FormsAuthentication (el mecanismo clásico de autenticación de ASP.NET).

public class AuthController : ApiController

{

    public string Get(string id)

    {

        FormsAuthentication.SetAuthCookie(id ?? "FooUser", false);

        return "You are autenthicated now";

    }

}

Vale, ahora puedes probar de realizar desde el navegador:

  1. Una llamada a /api/Auth/XXX (XXX nombre de usuario que quieras)
  2. Otra llamada a api/Secure y ver… como sigues sin estar autenticado.

La llamada  a FormsAuthentication lo que hace es colocar una cookie (llamada comúnmente ASPXAUTH) que es la cookie de autenticación de asp.net. Pero por alguna razón la estamos obviando. Bien, esta razón es que NO hemos definido modelo de seguridad en web.config. Si lo abres verás que hay la línea:

<authentication mode="None" />

Modificala para que sea:

<authentication mode="Forms" />

¡Y listos! Si repites el par de llamadas anterior, ahora verás como la llamada a /api/Secure si que te funciona, ya que ahora el proveedor de autenticación Forms utiliza la cookie y en base a ella crea un IPrincipal y lo autentica.

¿Qué, sencillo no? Pues no tanto…

Cuando usar y cuando no usar autenticación por Forms

Usar la autenticación Forms NO es mala idea si tus servicios WebApi van a ser utilizados tan solo desde el contexto de una aplicación web que antes haya autenticado al usuario. ¿Y por qué? Bueno… pues porque las cookies son algo muy del mundo web.

Pero si creas una API para ser usada en otros dispositivos o aplicaciones (p. ej. una aplicación nativa de móvil) usar cookies para autenticarnos es una mala idea, ya que entonces obligas a quien usa tus servicios a que ponga código para leer las cookies recibidas y enviarlas de nuevo. Eso, si usas un navegador, lo hace el navegador automáticamente.

Así que lo dicho: si tus servicios WebApi van a ser utilizados tan solo dentro de una aplicación web (p. ej. para darte soporte a llamadas Ajax) puedes usar el mecanismo que acabamos de ver. En este caso, habitualmente, los controladores WebApi se despliegan en el mismo proyecto que los de ASP.NET MVC (si no recuerda que deberás lidiar con cross-domain). Y quien autentica al usuario (o sea quien tiene la llamada a FormsAuthentication.SetAuthCookie) es un controlador de MVC (el que responde al formulario de Login, claro). Y los controladores WebApi los tienes decorados tan solo con el [Authorize].

Pero vamos a olvidarnos de este escenario y planteemos otro: estás creando simplemente una API. El consumidor de esta API va a ser una aplicación de móvil (p. ej.) o dicho de otro modo, no va a ser un browser.

Entonces NO debemos usar autenticación por Forms y debemos buscar otros mecanismos. La pregunta es… ¿Cuales?

Autenticación básica

Bueno… exploremos esta opción. La autenticación básica de HTTP es muy sencilla. Aunque tiene un flujo que empieza por mandar un 401 con una cabecera específica todo eso lo obviaremos (eso es porque los navegadores sepan que hay un proceso de autenticación pero en nuestro caso el cliente no es un navegador).

Asi, si nos centramos en como es una petición autenticada que use autenticación básica, es muy sencillo: Tiene una cabecera Authorization con este formato:

Authorization: Basic username:password

La única salvedad es que username:password se envía codificado en BASE64.

Vale… ¿y como implementamos eso en WebApi? Pues hay varias maneras, p. ej. nos podríamos crear un filtro de autorización propio:

public class BasicAuthorizeAttribute : AuthorizationFilterAttribute

{

    public override void OnAuthorization(HttpActionContext actionContext)

    {

        var headers = actionContext.Request.Headers;

        if (headers.Authorization != null && headers.Authorization.Scheme == "Basic")

        {

            try

            {

                var userPwd = Encoding.UTF8.GetString(Convert.FromBase64String(headers.Authorization.Parameter));

                var user = userPwd.Substring(0, userPwd.IndexOf(‘:’));

                var password = userPwd.Substring(userPwd.IndexOf(‘:’) + 1);

                // Validamos user y password (aquí asumimos que siempre son ok)

            }

            catch (Exception)

            {

                PutUnauthorizedResult(actionContext, "Invalid Authorization header");

            }

        }

        else

        {

            // No hay el header Authorization

            PutUnauthorizedResult(actionContext, "Auhtorization needed");

        }

    }

 

    private void PutUnauthorizedResult(HttpActionContext actionContext, string msg)

    {

        actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized)

        {

            Content = new StringContent(msg)

        };

    }

}

Nota: Para realizar tareas de autorización (como este caso) debemos usar un filtro de autorización. No uses para ello un filtro de acción (es decir, no derives de ActionFilterAttribute y redefinas OnActionExecuting). La razón es que los filtros de autorización se ejecutan antes que los filtros de acción, ya que precisamente su tarea es esa: autorizar la llamada a una acción. No está de más que te descargues el poster con el ciclo de vida de una petición WebApi de http://www.microsoft.com/en-us/download/details.aspx?id=36476

Ahora tan solo debemos decorar la acción Secure del controlador con [BasicAuthorize] en lugar de [Authorize] y ya tenemos la autenticación básica implementada (para pasar de cadena a base64 puedes usar cualquiera de las páginas que hay por ahí que lo hacen como http://www.motobit.com/util/base64-decoder-encoder.asp):

image

Si eliminar el tag Authorization verás como la respuesta pasa a ser un 401.

Por supuesto, la autenticación básica de HTTP es tan insegura que tan solo debería usarse sobre HTTPS.

Vale… pero quizá te estás preguntando si tenemos más alternativas que usar un filtro de autorización para validar si una petición está autorizada. Y la respuesta es que sí. Tenemos al menos dos más:

  1. Usar un Message Handler
  2. Usar un módulo de autenticación de ASP.NET

¿Te parece si exploramos ambas?

Usando un Message Handler

Los Message Handlers se ejecutan incluso antes que los filtros de autorización. Es más, se ejecutan incluso antes de que el pipeline de WebApi seleccione un controlador así que son un lugar propicio para poner código de autorización.

Los Message Handlers tienen la potestad de generar ellos mismos un resultado y entonces todo el resto de la pipeline de WebApi es eliminada. Es decir es posible que un Message Handler intercepte una petición, genere un resultado y entonces esta petición no será transferida al controlador a la cual debería haber llegado.

Esto puede parecer que hace que los Message Handlers sean un buen sitio para autorizar peticiones y lo son, pero NO son un buen sitio para rechazar peticiones no autorizadas. Me explico: sigamos con nuestro ejemplo de autenticación básica.

Si usas un Message Handler y rechazamos todas las peticiones que NO tengan la cabecera Authorize entonces tendremos un problema si necesitamos tener alguna parte de la API pública. Un Message Handler se ejecuta siempre. Para todas las peticiones.

Si quieres usar un Message Handler para autorización lo que debes hacer no es rechazar las peticiones que estén autorizadas (en nuestro caso que no tengan la cabecera Authorize). No. En su lugar debes autorizar aquellas peticiones válidas. ¿Como? Colocando un IPrincipal en el Thread. Y luego, en los controladores utilizas [Authorize].

Veamos un ejemplo rápido:

public class BasicAuthMessageHandler : DelegatingHandler

{

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,

        CancellationToken cancellationToken)

    {

        var headers = request.Headers;

        if (headers.Authorization != null && headers.Authorization.Scheme == "Basic")

        {

            var userPwd = Encoding.UTF8.GetString(Convert.FromBase64String(headers.Authorization.Parameter));

            var user = userPwd.Substring(0, userPwd.IndexOf(‘:’));

            var password = userPwd.Substring(userPwd.IndexOf(‘:’) + 1);

            // Validamos user y password (aquí asumimos que siempre son ok)

            var principal = new GenericPrincipal(new GenericIdentity(user), null);

            PutPrincipal(principal);

        }

 

        return base.SendAsync(request, cancellationToken);

    }

 

    private void PutPrincipal(IPrincipal principal)

    {

        Thread.CurrentPrincipal = principal;

        if (HttpContext.Current != null)

        {

            HttpContext.Current.User = principal;

        }

    }

}

Este Message Handler crea y coloca un GenericPrincipal si la cabecera Authorize está presente. Luego en el controlador debemos usar [Authorize] para aquellas acciones que requieran de usuario autenticado.

Acuerdate de registrar el Message Handler desde Application_Start:

config.MessageHandlers.Add(new BasicAuthMessageHandler());

Por lo tanto estamos usando una combinación entre un Message Handler y un filtro de autorización (Authorize).

Usando un módulo de autenticación

Bien… exploremos esta otra alternativa. Ahora vamos a usar un módulo de autenticación (un HttpModule) para realizar las mismas tareas que realiza el Message Handler, es decir para crear un IPrincipal.

¿Y qué diferencias hay entre usar un HttpModule o un Message Handler? Pues buena pregunta, básicamente las siguientes:

  1. Un HttpModule es algo específico de IIS. No lo puedes usar en aplicaciones WebApi que no estén hospedadas en IIS. Por otro lado un Message Handler es algo propio de WebApi.
  2. Un HttpModule ve todas las peticiones que estén dirigidas al pipeline de ASP.NET. Sean peticiones de WebApi o no. Un Message Handler tan solo ve las peticiones WebApi.
  3. Un HttpModule se ejecuta antes en el pipeline que un Message Handler. De hecho se ejecuta antes que cualquier parte de WebApi.

Por norma general, es preferible usar un HttpModule si sabes que vas a hospedar tu WebApi siempre en un IIS. Si no, si quieres tener la posibilidad de hospedar tu WebApi en otros procesos entonces usa un Message Handler.

¿Listo para nuestro módulo de autenticación? Aquí lo tienes:

public class BasicAuthModule : IHttpModule

{

     public void Init(HttpApplication context)

     {

         context.AuthenticateRequest += OnAuthenticateRequest;

     }

 

     private void OnAuthenticateRequest(object sender, EventArgs e)

     {

         var application = (HttpApplication)sender;

         var request = new HttpRequestWrapper(application.Request);

 

         var headers = request.Headers;

         var authData = headers["Authorization"];

         if (!string.IsNullOrEmpty(authData))

         {

             var scheme = authData.Substring(0, authData.IndexOf(‘ ‘));

             var parameter = authData.Substring(scheme.Length).Trim();

             var userPwd = Encoding.UTF8.GetString(Convert.FromBase64String(parameter));

             var user = userPwd.Substring(0, userPwd.IndexOf(‘:’));

             var password = userPwd.Substring(userPwd.IndexOf(‘:’) + 1);

             // Validamos user y password (aquí asumimos que siempre son ok)

             var principal = new GenericPrincipal(new GenericIdentity(user), null);

             PutPrincipal(principal);

         }

     }

 

     public void Dispose()

     {

 

     }

 

     private void PutPrincipal(IPrincipal principal)

     {

         Thread.CurrentPrincipal = principal;

         if (HttpContext.Current != null)

         {

             HttpContext.Current.User = principal;

         }

     }

}

Puedes ver como el código es muy parecido al del Message Handler. Ahora debemos registrarlo. Los HttpModules se registran en el web.config, dentro de la sección modules de system.webServer:

<system.webServer>

  <modules>

    <add name="BasicAuthHttpModule"

      type="MvcSecureDemo.BasicAuthModule, MvcSecureDemo"/>

  </modules>

</system.webServer>

La situación es la misma que teníamos en el caso del Message Handler: en los controladores debemos usar [Authorize] para proteger las acciones que requieran usuarios autenticados.

Más allá de autenticación básica

Vale… hemos explorado como securizar nuestros servicios WebApi (a través de filtros de autorización, Message Handlers y HttpModules). Lo hemos hecho a partir de la autenticación básica de HTTP porque es muy sencilla y así el código no queda liado. 😉

Pero autenticación básica NO es un buen mecanismo. No lo es, a menos que uses HTTPS, ya que el login y el password viajan en texto plano (recuerda que Base64 no es cifrado).

Bien, ¿qué debéríamos hacer si no tenemos HTTPS? Una solución pasa por encriptar realmente el login y el password. Esto sigue teniendo un riesgo, tan pequeño como seguro sea nuestro algoritmo de encriptación y segura esté la clave que usemos).

Exploremos otra alternativa, otra que signifique que ni el login ni el password viajan por la red. Nadie con un sniffer será capaz de saber nuestra password escuchando los mensajes que nos intercambiamos con el servidor… Veamos que deberíamos hacer.

Partamos de la suposición de que tanto el cliente (una aplicación móvil p. ej.) y el servidor comparten un código, llamésmole código de acceso. Da igual como lo han compartido (p. ej. a través de un email). Lo importante es que lo tienen.

Entonces básicamente si el cliente adjunta este código en una cabecera (sigamos suponiendo la misma cabecera Authorization) la llamada se considera autenticada y en caso contrario se considera válida. Este código (insisto: obtenido previamente) identifica al cliente (la aplicación móvil) y al usuario de dicho cliente, por lo que adjuntando este código una aplicación puede hacer peticiones en nombre del usuario.

Vale, no parece que hayamos progresado mucho verdad: alguien con un sniffer pilla nuestra petición y ya tiene el código. Muy seguro el sistema no parece.

Bueno… sigamos suponiendo. Sigamos suponiendo que además de este código, tanto cliente como servidor comparten otro código. Un código secreto. Lo de secreto viene porque este segundo código jamás viajará por la red. Nunca. Lo comparten al inicio de los tiempos (p. ej. por mail) y luego el cliente se lo guarda y el servidor también.

Ahora lo que debe hacer el cliente es mandar la petición pero usará el código secreto para generar un hash del código de acceso. Y la cabecera Authorization contendrá este hash. Cuando el servidor recibe una petición del cliente debe:

  • Calcular el hash del código de acceso del cliente usando el código secreto (que ambos comparten)
  • Si el resultado es el mismo que ha enviado el cliente, la petición se considera autenticada.

Vale… hay un problemilla ahora. El código secreto debe ser distinto por cada cliente, pero si tan solo recibimos en la cabecera Authorization el hash del código de acceso… ¿como sabemos qué código secreto debemos usar para calcular el hash?. Es decir, como sabemos de qué cliente es la petición.

Pues nada. Hacemos que cliente y servidor comparten otro elemento: un identificador de cliente. Ahora el cliente en la cabecera Authorization mandará su código identificador y el hash de su código de acceso (calculado con su código secreto). Cuando el servidor recibe la petición, sabe de que cliente es (por el identificador de cliente de la cabecera Authorization) y podrá usar el código secreto de este cliente para calcular el hash del código de acceso de este cliente y validar que sea el mismo que el clienté envía.

¿Te parece seguro el sistema ahora? No lo es en absoluto. Alguien que pille una petición podrá hacer lo que quiera, porque tendrá el hash del código de acceso. Estamos igual que al principio… pero a un paso de la solución.

El problema de que si nos pillan una petición luego ya nos puedan suplantar siempre es porque estamos calculando un hash de algo que jamás se modifica: el código de acceso. Porque en lugar de calcular un hash de dicho código no calculamos un hash de una cadena que esté compuesta de:

  1. La URL de destino
  2. Los datos en query string/formdata
  3. El código de acceso

Los datos 1 y2 son variables (distintos por cada petición que hagamos). Así cada petición tendrá un hash distinto. Cuando el servidor reciba la petición calculará esta cadena con la URL, la query string/formdata y el código de acceso del cliente y usará el código secreto del cliente para calcular el hash. Si coinciden la petición queda autenticada.

Ahora si alguien nos pilla una petición con un sniffer, tan solo podrá hacer una cosa: enviarla otra vez al servidor. No podrá modificarla, porque si lo hace (p. ej. modifica la querystring para cambiar un parámetro) automáticamente el hash pasa a ser inválido. Y no puede construir un hash nuevo porque no tiene acceso al código secreto.

Así pues un hacker nos puede pillar peticiones y puede ver su contenido. Hasta puede guardarlas y reenviarlas al servidor más adelante. Pero NO puede crear peticiones falsas en nuestro nombre.

Vayamos un paso más allá. ¿Por qué no adjuntamos el tiempo en que se realiza la petición? Es decir el cliente añade en una cabecera la fecha y hora en que realiza la petición. Y usa este dato también para calcular el hash. Ahora el servidor puede validar que la fecha/hora que envía el cliente sea (aproximadamente) la actual. Si el servidor recibe una petición de un cliente con una fecha/hora de hace 4 minutos, la puede aceptar pero si es de hace 1 hora la puede rechazar, ya que seguramente es una petición interceptada, guardada y mandada luego. Dado que la fecha/hora se usa también para calcular el hash, el hacker que nos intercepte la petición no puede falsear este dato.

Incluso podríamos hacer algo más: añadir un número (llamésmole nonce) de secuencia. La idea es que dos peticiones del mismo cliente jamás pueden repetir el nonce. Por supuesto el nonce se manda en otra cabecera y también se usa para calcular el hash. Si ahora un hacker nos intercepta la petición y la intenta mandar al cabo de 3 minutos… será rechazada porque este nonce ya ha sido usado.

Ahora estamos protegidos de todos los ataques, excepto de un Man-in-the-middle. Ojo, no tenemos privacidad (tanto las peticiones como las respuestas van sobre HTTP en texto llano), pero nuestras credenciales están seguras y nadie puede crear peticiones en nuestro nombre ni guardarse peticiones válidas y enviarlas más adelante. Si requerimos privacidad y protección contra ataques tipo Man-in-the-middle entonces lo más rápido es usar HTTPS.

Por supuesto este sistema que he descrito, no me lo he inventado yo. Este sistema lo inventó Blain Cook y le dio el nombre de oAuth. Lo que he descrito aquí es (rápido y mal, por supuesto) el flujo básico de oAuth 1.0.

Las ventajas de oAuth son que en ningún momento las credenciales del usuario circulan por la red y que ofrece un buen balance de seguridad siempre y cuando el código secreto no se vea comprometido. Es pues una muy buena opción para proteger tus servicios WebApi.

Y por supuesto, usar otros mecanismos de autenticación no modifica en nada lo dicho en este post, tan solo “complica” el código que has de poner en tu filtro de autorización, message handler o HttpModule.

Un saludo!

Objective-C para desarrolladores de C# (i)–Introducción

Muy buenas! Con este post inicio una serie de posts (como siempre, ni idea de cuantos van a ser) dedicado especialmente a desarrolladores de C# que quieran empezar con Objective-C. No soy un experto en Objective-C ni esta serie pretende que te conviertas en un experto en este lenguaje. Tampoco es un tutorial de Objective-C. Es simplemente una ayuda para todos aquellos desarrolladores con un background de C# y .NET que tengan curiosidad por ver como es el lenguaje de la manzana.

A lo largo de esta serie intentaré tocar el máximo número de temas y eso incluirá:

  • Lenguajes: Vamos a comparar las características intrínsecas de ambos lenguajes. Por intrínsecas me refiero a las características que no dependen de ninguna API o librería externa como sintaxis, tipos básicos, etc…
  • Herramientas: Por mucho que sean posts de Objective-C y de C# ambos lenguajes están muy enfocados a plataformas muy concretas y se suelen usar con herramientas muy concretas. Así que hablaré de XCode y de Visual Studio. Pero eso no quita que existan otras herramientas para ambos lenguajes.
  • Plataforma: Los lenguajes, si nos ceñimos a su definición, son agnósticos de plataforma. Pero vamos a terminar hablando de plataforma, porque todo lenguaje necesita una que le de soporte. En el caso de C# tenemos la BCL y luego todo .NET. En Objective-C tenemos Foundation y luego Cocoa y las apis de iOS (no hablaré de desarrollo para MacOS porque no tengo ni idea). Así que, en algún momento, compararemos las plataformas asociadas a cada lenguaje. Por supuesto esta comparación no será, porque no lo pretende porque no puede, ser una comparación exhaustiva.

Todos los posts de la serie estarán escritos des del punto de vista de alguien que viene (y por lo tanto conoce) el mundo de C# y .NET. Esta serie no busca en ningún momento un ganador. Por eso que nadie busque en las comparaciones vencedores y perdedores. Eso queda en el juicio de cada uno.

Y finalmente… la pregunta del gritón de dólares: ¿Necesito un ordenador de Cupertino para seguir la serie?

Pues para seguirla toda, toda, toda pues obviamente sí. Cuando hablemos de XCode o de Cocoa vas a necesitar un Mac si quieres “hacer ejemplos en vivo”.

De todos modos doy por supuesto que si te ha picado la curiosidad por Objective-C es que te estés planteando el desarrollar para iOS, por lo que necesitarás un Mac tarde o temprano 😛 Pero, es posible hacer muchos de los ejemplos que presentaré en un PC con Windows. Existe el runtime de Objective-C para Windows, por lo que si lo que pretendes es simplemente trastear con Objective-C podrás hacerlo desde Windows. Obviamente con limitaciones.

Luego ya podrás decidir si prefieres comprarte un Mac o bien prefieres contactar con Juan Fco. Miranda quien te guiará por los sinuosos caminos del Hackintosh.

Instalación de Objective-C en Windows

Bueno, el primer paso es ir a la página de descargas para Windows de GNUStep y descargarte:

  1. GNUstep MSYS System
  2. GNUstep Core
  3. GNUstep Devel

Luego instalatelos en este mismo orden. Yo por ejemplo los tengo instalados en D:GNUStep

GNUStep consiste en una serie de herramientas, como gcc para compilar Objective-C y también tiene ports de parte de la plataforma (está Foundation y parte de Cocoa implementado).

GNUStep es para hombres y no viene con ningún IDE ni nada parecido. Aunque técnicamente no necesitas ninguno ya que GNUStep te habrá instalado make.exe. Yo no conozco ningún IDE de Objective-C para Windows por ahí (personalmente no uso Objective-C bajo Windows).

Para probar si GNUStep está bien instalado vamos a realizar nuestro HelloWorld.

Abre tu editor de texto favorito y crea un fichero llamado HelloWorld.m con el siguiente código:

#import <Foundation/Foundation.h>
int main (void)
{
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        NSLog (@"Hello, World!");
        [pool drain];
        return;
}

Guardalo como HelloWorld.m (la extensión .m es la que se suele usar para crear archivos Objective-C)

Ahora nos toca usar gcc.exe para compilar este archivo. Ello deberemos hacerlo desde línea de comandos. Abres una línea de comandos y te vas donde tengas el archivo HelloWorld.m y tecleas (todo en una misma línea):

gcc HelloWorld.m -I D:/GNUstep/GNUstep/System/Library/Headers -L D:/GNUstep/GNUstep/System/Library/Libraries -fconstant-string-class=NSConstantString -o HelloWorld.exe -lobjc -lgnustep-base

Las opciones que estamos usando son las siguientes:

  • -I <path_includes>: Path raíz de los archivos de cabecera
  • -L <path_libraries>: Path raíz de los archivos de librería
  • -fconstant-string-class <clase>: Nombre de la clase a usar cuando haya constantes string.
  • -o <fichero>: Nombre del fichero de salida
  • -lobjc: Para enlazar con la librería de objective C
  • -lgnustep-base: Para enlazar con la librería de GnuStep

Esto te debería compilar y generar el HelloWorld.exe… Si es así, ya estás listo para empezar a programar con Objective-C bajo Windows 😉

En sucesivos posts veremos como compilar usando XCode (por si tienes un Mac) y empezaremos a ver las diferencias entre Objective-C y C#).

Nos vemos!

[OT] Duelo: El juego de Euler (1)

Bueno… Está por ahí Quique, que como se aburre se ha decidido a picarme un poco (pobre mortal ^_^).

Se ve que junto con Álex se han embarcado en resolver los problemas de Euler en distintos lenguajes… Álex se ha quedado con F# (el patito desconocido de .NET), mientras que Quique se ha armado con todo el poder de (mi amado) C#.

Dado que Toni Recio se ha sumado y ha pillado Javascript (quien lo ha visto y quien lo ve) yo he decidido participar, pero esta vez armado con todo el potencial de un lenguaje de programación funcional de verdad. Y el elegido ha sido Scala.

Cada post que haga con la solución aprovecharé para intentar comentar algo de Scala. Ya, Scala no es .NET, pero lo pongo en este blog porque no tengo otro y me da muuuucha pereza abrirlo. Así que… :p

Bueno, al tajo. El primer reto es sencillo (si todos son así, vamos bien): Sumar todos los números del 1 al 1000 que sean divisibles entre 3 ó entre 5. Pues al tajo:

package duel.Euler

object Euler1 extends App {

      println(

          (1 until 1000).filter(n=> (n % 3 == 0) || (n % 5 ==0 )).foldLeft(0)(_+_)

      );

}

¡Listos!

Si conocéis LINQ no hay mucho que añadir:

  1. La construcción (1 until 1000) es equivalente a Enumerable.Range
  2. filter es nuestro amado Where
  3. foldLeft equivale al Aggregate de LINQ. Usado con la sintaxis (_+_) equivale al Sum() de LINQ.

Y que narices es esto de foldLeft

Pues bien, foldLeft es una función existente en todas las colecciones de Scala que básicamente permite ejecutar una función que acepte dos parámetros (que serán sacados iterando por la colección). Además foldLeft proporciona un valor inicial.

La sintaxis básica de foldLeft es:

coleccion.foldLeft(valor_inicial) función_a_ejecutar

En nuestro caso está claro:

  1. La colección son los números de 1 a 1000 que son divisibles entre 3 ó 5
  2. El valor inicial es 0
  3. La función a ejecutar es (_+_). Esta es una sintaxis especial de Scala que equivale a una función anónima que suma los dos operandos que se le pasan.

De hecho un código totalmente equivalente hubiese sido usar foldLeft(0)((a,b) => a+b). En este caso estamos pasando la función a usar (sumar los dos operandos) de forma más explícita.

Listos para el siguiente reto 😉