Cliente REST Android

17 Junio 2010 4 comentarios »

Si quieres jugar haciendo operaciones REST con JSON en Android, y no tienes nada hecho, esto te puede servir de ayuda.

package packageName_00.PackageName_01;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.json.JSONObject;
import android.util.Log;

public class RestClient {

    public interface RequestCallback {
    	public void onError(Throwable exception);
    	public void onResponseReceived(HttpResponse response);
    }

    public static void doGet(final String url, final RequestCallback callback) {
    	Log.i("doGet", " - url: " + url);
    	final HttpClient httpClient = new DefaultHttpClient();
    	HttpConnectionParams.setConnectionTimeout(httpClient.getParams(), 10000);
    	Thread thread = new Thread(){
    		public void run() {
    	        HttpGet httpget = new HttpGet(url);
    	        HttpResponse response;
    	        try {
    	            response = httpClient.execute(httpget);
    	            callback.onResponseReceived(response);
    	        } catch (Exception ex) {
    	        	callback.onError(ex);
    	        }
    		}
    	};
    	thread.start();
    }

    public static void doPost (final String url,final JSONObject json, final RequestCallback callback) {
    	Log.i("doPost a url: " + url, "- JSON: " + json.toString());
    	final HttpClient httpClient = new DefaultHttpClient();
    	HttpConnectionParams.setConnectionTimeout(httpClient.getParams(), 10000);
    	Thread thread = new Thread(){
    		public void run() {
    			HttpPost httpPost = new HttpPost(url);
    	    	httpPost.addHeader("Accept", "application/json");
    	    	httpPost.addHeader("Content-Type", "application/json");
    	    	try {
    	    	    StringEntity entity = new StringEntity(json.toString(), "UTF-8");
    	    	    entity.setContentType("application/json");
    	    	    httpPost.setEntity(entity);
    	    	    // execute is a blocking call, it's best to call this code in a thread separate from the ui's
    	    	    HttpResponse response = httpClient.execute(httpPost);
    	    	    callback.onResponseReceived(response);
    	    	}
    	    	catch (Exception ex) {
    	    		callback.onError(ex);
    	    	}
    		}
    	};
    	thread.start();
    }

    public static void doPut (final String url,final JSONObject json,final RequestCallback callback) {
    	Log.i("doPut a url: " + url, "- JSON: " + json.toString());
    	final HttpClient httpClient = new DefaultHttpClient();
    	HttpConnectionParams.setConnectionTimeout(httpClient.getParams(), 10000);
    	Thread thread = new Thread(){
    		public void run() {
    			HttpPut httpPut = new HttpPut(url);
    			httpPut.addHeader("Accept", "application/json");
    			httpPut.addHeader("Content-Type", "application/json");
    	    	try {
    	    	    StringEntity entity = new StringEntity(json.toString(), "UTF-8");
    	    	    entity.setContentType("application/json");
    	    	    httpPut.setEntity(entity);
    	    	    HttpResponse response = httpClient.execute(httpPut);
    	    	    callback.onResponseReceived(response);
    	    	}
    	    	catch (Exception ex) {
    	    		callback.onError(ex);
    	    	}
    		}
    	};
    	thread.start();
    }

    public static void doDelete (final String url, final RequestCallback callback) {
    	Log.i("doDelete" , " - url: " + url);
    	final HttpClient httpClient = new DefaultHttpClient();
    	HttpConnectionParams.setConnectionTimeout(httpClient.getParams(), 10000);
    	Thread thread = new Thread(){
    		public void run() {
    			HttpDelete httpDelete = new HttpDelete(url);
    			httpDelete.addHeader("Accept", "application/json");
    	    	try {
    	    	    HttpResponse response = httpClient.execute(httpDelete);
    	    	    callback.onResponseReceived(response);
    	    	}
    	    	catch (Exception ex) {
    	    		callback.onError(ex);
    	    	}
    		}
    	};
    	thread.start();
    }
}

Para hacer consultas desde el emulador a un servidor en la propia máquina, esto es, una consulta ‘localhost’, debes usar la IP 10.0.2.2

GWT con REST

15 Junio 2010 Comentar »

Con este ejemplo, se muestra una forma de usar la nueva clase CellTable, que viene en GWT 2.1 para crear una interfaz de usuario sobre los servicios REST que se explicaron en este post.
Para ver como queda la cosa sin tener que instalar nada, se puede acceder a los servicios REST a través de aquí, y a la interfaz de usuario a través de aquí.

Si se utiliza Firefox existe un Addon, JSONView, que hace más amigable el trato con información en formato JSON.

Para ver el ejemplo en local habría que ejecutar desde el directorio raíz del archivo descomprimido:
grails run-app
Y acceder a través de:
http://localhost:8080/GrailsRestExample/gwt/index

Si se desea generar el archivo war para proceder a su instalación en un contenedor J2EE, habría que ejecutar desde el directorio raíz del archivo descomprimido el comando:
grails war
Y proceder a su instalación como cualquier aplicación web Java. Las aplicaciones Grails son aplicaciones web Java.

REST con Grails

12 Junio 2010 1 comentarios »

Para ejecutar el ejemplo hay que tener instalado Grails 1.3.1, descargarse el ejemplo , descomprimir el archivo y ejecutar en el directorio raíz del mismo:
grails run-app

No lo he complicado mucho para que el que quiera arrancar con Grails y REST se lie lo menos posible.
La aplicación consta de tres recursos, Usuario, Voto y Asunto. Se puede probar usando el programa rest-client o el Addon de Firefox ‘Poster’.

Recurso ‘Usuario’

  • Si se quieren consultar los usuarios se debe hacer una petición

GET http://localhost:8080/GrailsRestExample/users?max=20&offset=2

Donde max es el número máximo de resultados devueltos (por defecto 20) y offset es el índice a partir del que se desea obtener el primer resultado (por defecto 0)

  • Para obtener la información de un usuario concreto:

GET http://localhost:8080/GrailsRestExample/users/${idUsuario}

  • Para borrar un usuario se debe hacer una petición:

DELETE http://localhost:8080/GrailsRestExample/users/${idUsuario}

  • Para actualizar un usuario existente habría que hacer una petición:

PUT http://localhost:8080/GrailsRestExample/users/${idUsuario}
Enviando una representación JSON del usuario que se desee crear con las siguientes características:
{"username":"username", "email":"email@gruposp2p.org", "dateOfBird":"01-02-2003","enabled":"true"}

  • Para crear un nuevo usuario habría que hacer una petición

POST http://localhost:8080/GrailsRestExample/users
Enviando una representación JSON del usuario que se desee crear con las siguientes características:
{"username":"username", "email":"email@gruposp2p.org", "dateOfBird":"01-02-2003","enabled":"true"}

Recurso ‘Asunto’

  • Si se quieren consultar los Asuntos dados de alta en el sistema se debe hacer una petición

GET http://localhost:8080/GrailsRestExample/subjects?max=20&offset=2
Donde max es el número máximo de resultados devueltos(por defecto 20) y offset es el índice a partir del que se desea obtener el primer resultado (por defecto 0)

  • Para obtener la información de un asunto concreto:

GET http://localhost:8080/GrailsRestExample/subjects/${idSubject}

  • Para actualizar un asunto existente habría que hacer una petición:

PUT http://localhost:8080/GrailsRestExample/subjects/${idSubject}
Enviando una representación JSON del asunto que se desee crear que tenga siguientes características:
{"content":"Contenido del asunto 40","name":"Nombre del asunto40"}

  • Para borrar un asunto:

DELETE http://localhost:8080/GrailsRestExample/subjects/${idSubject}

Recursos ‘Asuntos’ asociados a un determinado recurso ‘Usuario’

  • Para obtener todos los asuntos generados por un usuario concreto

GET http://localhost:8080/GrailsRestExample/users/${idUsuario}/subjects/

  • Para generar un nuevo asunto asociado al usuario ${idUsuario} habría que hacer una petición

POST http://localhost:8080/GrailsRestExample/users/${idUsuario}/subjects/
Enviando una representación JSON del asunto que se desee crear con las siguientes características:
{"content":"Contenido del asunto 40","name":"Nombre del asunto40"}

Recurso ‘Voto’

  • Si se quieren consultar todos los Votos dados de alta en el sistema se debería hacer una petición

GET http://localhost:8080/GrailsRestExample/votes?max=20&offset=2
Donde max es el número máximo de resultados devueltos (por defecto 20) y offset es el índice a partir del que se desea obtener el primer resultado (por defecto 0)

  • Si se quiere consultar un voto concreto

GET http://localhost:8080/GrailsRestExample/votes/${idVote}

  • Si se quiere modificar un voto habrá que hacer una petición

PUT  http://localhost:8080/GrailsRestExample/votes/${idVote}
Enviando una representación JSON del asunto que se desee crear que tenga siguientes características:
{"value":"valor del voto www"}

  • Para eliminar un voto:

DELETE http://localhost:8080/GrailsRestExample/votes/${idVote}

Votos asociados a un determinado usuario

  • Para obtener todos los votos generados por el usuario ${idUsuario}

GET http://localhost:8080/GrailsRestExample/users/${idUsuario}/votes/

  • Para generar un nuevo voto sobre el asunto ${idSubject} asociado al usuario ${idUsuario} habría que hacer una petición

POST http://localhost:8080/GrailsRestExample/users/${idUsuario}/subjects/${idSubject}
Con una representación JSON del voto que tuviera las siguientes características:
{"value":"valor del voto www"}

Votos asociados a un determinado asunto
GET http://localhost:8080/GrailsRestExample/subjects/{idSubject}/votes

Votos asociados a un determinado asunto y a un determinado usuario
GET http://localhost:8080/GrailsRestExample/users/${idUsuario}/subjects/{idSubject}/votes

En el siguiente artículo explicaré cómo usar las nueva clase TableCell que viene con GWT 2.1 utilizando los datos disponibles en estos servicios REST, la aplicación de acceso para Android la dejaré para el final de esta serie.

Es importante quedarse con los siguientes puntos:

  • Existen formas de securizar los recursos.
  • El desarrollo está hecho en Grails, pero utilizando principios REST pueden crearse servicios, independientes de lenguaje de programación y plataforma, accesibles a través de Internet.
  • Gracias a esta técnica se separa completamente la interfaz de usuario del servicio.
  • Si se desea que dos partes intercambien información a través de Internet la mejor forma de conseguirlo es empezando definiendo las interfaces REST de los recursos que se desean compartir.

Twitteando en caliente

10 Junio 2010 2 comentarios »

He escrito un Tweet que parece que no ha sentado bien a alguna gente. Lo explicaré un poco para que se entienda.
Comiendo he visto una noticia en la que se decía que había que tener mucho cuidado con la información que se daba porque con el simple número de NIF ya podían enmarronarte haciendo compras y cosas así. Como si no fuera fácil conseguir números de NIF. Evidentemente no daban nombres de nada ni concretaban, un FUD en toda regla.

El Tweet lo he soltado en caliente indignado y decía ‘Sobre temas de robo de identidad, vale que no lo sepa una persona normal, pero que un profesional no sepa lo que es OCSP señala el nivel’, algo que fuera de contexto se puede malinterpretar.

La cosa más explicada debería quedar mas o menos así, si se hacen trámites con firma electrónica las aplicaciones que hagan uso de esas firmas pueden comprobar en tiempo real si los certificados asociados son válidos. En caso de pérdida o robo la información se actualiza una vez se ha denunciado la pérdida. Alguien dedicado a la gestión de identidades electrónicas debe saber eso.

Instalación del DNI electrónico en Ubuntu Lucid

27 Mayo 2010 Comentar »

NOTA – 3 de Junio – Parece que ya han arreglado las librerías de los repositorios

————————————————————————————————————————

Seguramente existirá otra forma mejor de conseguirlo pero lo que explico a continuación me ha funcionado.

Todavía no existe software para la versión 10.04 de Ubuntu, Ubuntu Lucid, así es que empecé descargando la versión opensc-dnie_1.4.7 que sólo existe para la Karmic Koala. La cosa no funcionó, tuve que probar con la versión 1.4.6 que existe para la Jaunty Jackalope y con eso si que he conseguido usar el DNI desde Firefox, pero seguiendo estos pasos:

Instalar, por este orden, los paquetes que traen la distribución 1.4.6 descargarbles desde el portal oficial del DNI electrónico: libopensc2_0.11.7-7_i386.deb, opensc_0.11.7-7_i386.deb y opensc-dnie_1.4.6-2_i386.deb.
Si se empieza instalando opensc-dnie, se instalarán las librerías que hay en el repositorio en vez de las que vienen con la distribución y eso me ha dado fallos.

La primera vez que lo he usado en Firefox he tenido que cargar manualmente el módulo criptográfico, para ello hay que ir a Editar > Preferencias > Dispositivos de seguridad > Cargar y seleccionar el archivo /usr/lib/opensc-pkcs11.so

Debido a este bug, el demonio pcscd no arranca automáticamente en Lucid, así es que, por lo pronto, cada vez que se quiera utilizar el DNI electrónico habrá que abrir una consola y ejecutar:
sudo /etc/init.d/pcscd start

Cuidado con lo que instalas

14 Mayo 2010 Comentar »

Los programas informáticos no son como los libros ni como las películas, no son productos ‘pasivos’, son activos, y están instalados en los dispositivos que te acompañan, gestionan las empresas y están en nuestros dormitorios con cámaras incorporadas. Si no se tiene cuidado con lo que se instala, se pueden acabar ejecutando programas que hagan cosas que realmente no quieres que hagan, esa es sólo otra razón más por la que algunos defendemos el software libre.
Que una persona, voluntariamente, elija instalar programas que no sabe lo que llevan dentro es algo a lo que nadie puede objetar nada, lo malo, es que aunque no quieras, se den las circunstancias para que te veas en la obligación de tener instalado en tus dispositivos ‘cajas negras’, eso, en un escenario en el que cada vez tenemos mas dispositivos a nuestro alrededor, y si no se está poniendo el ‘cazo’, es una aberración que no se le debería de ocurrir ni al que asó la manteca.
Desde el punto de vista de ‘producto’ un programa informático se parece mucho mas a un yogur que a un libro, es algo sobre lo que se deberían hacer inspecciones de seguridad.

Principal diferencia entre pago normal y micropago

7 Mayo 2010 Comentar »

La principal diferencia entre los pagos normales y los micropagos se encuentra en las comisiones que se cobran al realizar los mismos. Para entenderlo basta mirar estos datos:

pagar 1.00 euro -> comisión micropago=0.10, comisión normal=0.33
pagar 5.00 euros -> comisión micropago=0.30, comisión normal=0.45
pagar 10.00 euros -> comisión micropago=0.55, comisión normal=0.59
pagar 12.00 euros -> comisión micropago=0.65, comisión normal=0.65 (punto de encuentro)
pagar 14.00 euros -> comisión micropago=0.75, comisión normal=0.71
pagar 16.00 euros -> comisión micropago=0.85, comisión normal=0.76

La información se refiere a una entidad extrangera, ahora mismo no se de ninguna entidad española que trabaje con micropagos.

Configuración de Grails para usar el DNI electrónico como mecanismo de autentificación

1 Mayo 2010 Comentar »

Entorno -> Grails 1.2.2

Para esta aplicación es necesario tener un servidor configurado para que solicite certificados al acceder a un recurso seguro, en esta página se explican los detalles

grails create-app AutentificacionDNIe
cd AutentificacionDNIe
grails install-plugin spring-security-core
grails s2-quickstart org.gruposp2p.openid.provider UserDNI RoleDNI

Se crea el controlador cuyo acceso se quiera securizar con DNI electrónico:

grails create-controller secure

Para solicitar el acceso del DNIe se configura la aplicación para que el acceso al controlador se haga exclusivamente a través del protocolo HTTPS. Para ello se edita ‘Config.groovy’ y se añade:

grails.plugins.springsecurity.useX509=true
grails.plugins.springsecurity.x509.subjectDnRegex = 'SERIALNUMBER=(.*?),'
grails.plugins.springsecurity.portMapper.httpsPort=8443
grails.plugins.springsecurity.secureChannel.definition = ['/secure/**':'REQUIRES_SECURE_CHANNEL',
	                                                          '/**': 'ANY_CHANNEL']

Para comprobar que todo funciona se edita BootStrap.groovy y se añade un usuario de pruebas

	def init = { servletContext ->
	   def adminRole = new RoleDNI(authority: 'ROLE_ADMIN').save(flush: true)
	   String password = springSecurityService.encodePassword('password')
	   def testUser = new UserDNI(username: 'NumeroNIFDelDNIConQueSePrueba', enabled: true, password: password)
	   testUser.save(flush: true)
	   UserDNIRoleDNI.create testUser, adminRole, true
	}

Crear secure/index.gsp con

<sec:ifLoggedIn>
	Buenas <sec:loggedInUserInfo field="username"/>
</sec:ifLoggedIn>
<sec:ifNotLoggedIn>
	Acceso no autorizado
</sec:ifNotLoggedIn>

Para probar la aplicación ejecutar

grails run-app

… y acceder a la aplicación

Por qué son importantes los micropagos

27 Abril 2010 Comentar »
Hay muchos escenario de este mundo donde se pasa verdaderas necesidades por falta de medios para resolver sus problemas y hay otros sitios en los que se tienen ganas de ayudar pero no se encuentran los canales por los que poder enfocar esa ayuda.
Mediante Internet se presenta una oportunidad como no ha existido hasta la fecha para poder encauzar esas voluntades.
Los principales problemas son:
  • La ausencia de una cultura de micropagos y depósitos que faciliten flujos monetarios transparentes.
  • La monitorización en tiempo real del destino de los medios. Que se sepa donde ha ido y donde esta yendo hasta el último céntimo para que no haya lugar a la mas ligera suspicacia. Con Internet es posible.
Eso sólo se puede conseguir con líderes hábiles y con programas informáticos, no son opciones excluyentes aunque mientras que los líderes ‘te quitan’ el poder para su uso, los programas te dan el poder a ti … en vista de los resultados obtenidos hasta la fecha he decidido apostar una temporada ‘full-time’ por los programas.
No digo que sea la piedra filosofal ni la solución a todos los problemas del planeta, pero se emplean esfuerzos en otro tipo de cosas que para mi son mucho menos importantes y entiendo que incluso puede que sean necesarias, no seré el que las juzgue. El desarrollo de este tipo de programas en principio es algo que no debería molestar a nadie.

Configuración de un cliente OpenID con Spring Security y Grails

26 Abril 2010 Comentar »
Para este artículo se ha utilizado la versión 1.3.0.RC2 de Grails, OpenId4Java y la versión 3.0.2 de Spring Security. Como entorno de desarrollo estoy usando SpringSource Tool Suite.
Aunque Grails dispone de una serie de plugins para las configuraciones de seguridad de las aplicaciones, quiero mantener durante un tiempo los vínculos con el mundo J2EE tradicional por si por lo que sea hay que ‘reenfocar’ de forma rápida algún proyecto. Por eso por lo pronto prefiero usar Spring Security a la manera tradicional Java. La integración de Grails con Java es tan buena que permite hacer este tipo de cosas sin problemas. Esta técnica la aprendí en este artículo:

    Para crear la aplicación ejecutar desde la consola de comandos:

> grails create-app ClienteOpenID
Se puede ejecutar la aplicación para ver que todo va bien:
> cd ClienteOpenID
> grails run-app

    Instalar la plantilla web.xml

> grails install-templates
Este comando crea el archivo src/templates/war/web.xml que se debe editar para añadir después del último filtro:
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

Y

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Instalar las librerías

Una vez descargadas las librerías arriba indicadas al comienzo del artículo copiar en el directorio lib del proyecto Grails:

  • spring-security-config-3.0.2.RELEASE.jar, spring-security-core-3.0.2.RELEASE.jar y spring-security-web-3.0.2.RELEASE.jar de Spring Security.
  • las librerías openid4java-full-0.9.5.jar, commons-httpclient-3.0.1.jar, xercesImpl-2.9.1.jar, y nekohtml-1.9.7.jar que se pueden encontrar en la distribución del archivo openid4java.

Configuración del filtro de seguridad

Existen dos formas de configurar el filtro. Bien declarando los beans en grails-app/conf/spring/resources.groovy o declarándolos en grails-app/conf/spring/resources.xml, si se hace editando resources.xml:
<beans xmlns:sec="http://www.springframework.org/schema/security"
  xmlns="http://www.springframework.org/schema/beans"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
              http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd
              http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<sec:http>
        <sec:intercept-url pattern="/secure/**" access="ROLE_BUYER"/>
        <sec:intercept-url pattern="/login*" filters="none"/>
        <sec:logout/>
        <sec:openid-login login-page="/login" authentication-failure-url="/login?login_error=true">
            <sec:attribute-exchange>
                <sec:openid-attribute name="email" type="http://schema.openid.net/contact/email" required="true" count="2"/>
                <sec:openid-attribute name="transaction" type="" />
            </sec:attribute-exchange>
        </sec:openid-login>
    </sec:http>

    <sec:authentication-manager>
	<sec:authentication-provider user-service-ref="springSecurityUserDetailsService"/>
    </sec:authentication-manager>

</beans>
Con Spring Security se puede especificar en el archivo de configuración el tipo de información que se va a intercambiar con el proveedor del servicio OpenID. Si el proveedor ofrece esos servicios responderá con la información oportuna. En este caso intercambiaremos el correo del usuario que se quiera identificar, y un campo transaction en el que irá la información del micropago .
En el archivo se puede ver que para autentificar se utiliza el bean springSecurityUserDetailsService, este bean es un servicio que implementa la interfaz UserDetailsService que devuelve al autentificador una instancia de UserDetails. La instancia de UserDetails es una clase de dominio, la clase User, que implementa dicha interfaz.
Para generar mediante Scaffolding una aplicación para la gestión de una determinada clase de dominio, en este caso User:
>grails generate-all User
Y decir a todo que si.
Para probar la aplicación se vuelve a ejecutar:
>grails run-app
Y se introduce en la base de datos un usuario que tenga como propiedad Username el valor del identificador OpenID que quieras probar en la aplicación y como authority ROLE_USER. Para ello acceder mediante el navegador a http://localhost:8080/ClienteOpenID/ pulsar sobre UserController, e introducir un usuario.
El proyecto completo con todas las librerías se puede descargar desde aquí.
Para importarlo desde SpringSource Tool Suite:
File > Import > Existing projects into Workspace
Del código se deduce que vengo del mundo Java :-) . Hay varias cosas que con Groovy quedarían mucho mas elegantes, pero no hace falta saber utilizar Grails al 100% para poder ir sacándole poco a poco todas las ventajas que ofrece, de momento me siento más seguro sin dejar del todo el mundillo J2EE.
En próximos artículos explicaré como implementar el servidor OpenID que, en este caso, servirá para hacer transacciones utilizando como mecanismo de identificación el DNI electrónico.