Mostrando entradas con la etiqueta shiro. Mostrar todas las entradas
Mostrando entradas con la etiqueta shiro. Mostrar todas las entradas

lunes, 4 de agosto de 2014

Creando un Realm personalizado para Shiro que permita leer los usuarios de una fuente externa


Como ya hemos vistos en alguno de los post anteriores Apache Shiro es una buena herramienta para las tareas de seguridad mas comunes dentro de una aplicación J2EE. Una de las formas que tiene este framework para permitirnos definir toda la configuración de la seguridad de nuestra aplicación de una manera declarativa y externa a la misma es mediante la creación de un archivo .ini con la siguiente estructura.

[main]
authc.loginUrl = /jsp/login.xhtml
authc.successUrl = /jsp/index.xhtml

[users]
admin=LECTOR
admin=EDITOR

[roles]
LECTOR=nota:leer
EDITOR=nota:crear,modificar

[urls]
/jsp/listaNotas.xhtml=perms["nota:leer"]
/jsp/insertarNota.xhtml=roles["EDITOR"]
/jsp/** = authc

Sin embargo, con frecuencia es posible rellenar de antemano todas las secciones anteriores excepto la de los usuarios. Es muy común que en las aplicaciones de hoy en día obtengamos la información de los usuarios a partir de otro tipo de recursos tales como una Base de Datos LDAP que sin duda nos brindan una mayor flexibilidad para el manejo de los cambios en los mismos (altas y bajas), así como mayor seguridad que un simple archivo de texto. ¿Pero que pasaría si no quisiésemos renunciar a la idea de definir nuestra configuración de seguridad en un archivo .ini pero necesitásemos obtener los usuarios de una fuente externa?

Excavando en la muy bien diseñada arquitectura de Shiro encontramos el concepto de Realm que es una interfaz para dado el nombre y contraseña del usuario actual recuperar la información de autenticación o autorización del mismo, dada que se cuenta con que esta almacenada en un sitio externo. Shiro posee varias clases que implementan esta interfaz para los casos mas comunes tales como :

  • AbstractLdapRealm
  • ActiveDirectoryRealm
  • JdbcRealm
  • JndiLdapRealm
  • IniRealm


Este ultimo es el Realm autorizado en el caso en que usemos un archivo ini. Mirando en el código fuente vemos que su funcionamiento interno consiste en parsear el archivo y extraer cada una de las secciones. Es de esta forma que nos es posible reutilizar esta clase a través de la herencia, pero sustituir en nuestra clase hija el fragmento en el que se cargan los usuarios por nuestra propia forma de obtenerlos. Un ejemplo sería como el que sigue:

...
public class IniConUsuarioExternoRealm extends IniRealm {

private static final String INI_FILE = "/WEB-INF/shiro.ini";

@Override
protected AuthenticationInfo doGetAuthenticationInfo

(AuthenticationToken token) throws AuthenticationException {
actualizarDatosDeUsuario();
return super.doGetAuthenticationInfo(token);
}

@Override
protected void onInit() {
this.setResourcePath("classpath:" + INI_FILE);

super.onInit();
}

public void actualizarDatosDeUsuario

(AuthenticationToken token) {
Map<String, Object> map = FacesContext.getCurrentInstance().

getExternalContext().getSessionMap();

String user = token.getUser();
String pass = token.getPs();
String[] roles = //Aqui obten los roles para tu usuario 

//de donde quiera que los tengas

if (StringUtils.isBlank(user)) {
throw new AuthorizationException("No hay usuarios ni roles");
}

construirCuenta(user, "", roles);
}

private SimpleAccount construirCuenta

(String username, String password, String[] roles) {
SimpleAccount account = getUser(username);
if (account == null) {
account = new SimpleAccount(username, password, getName());
add(account);
}

account.setCredentials(password);

if (roles != null) {
for (int i = 0; i < roles.length; i++) {
String rolename = roles[i];
account.addRole(rolename);

SimpleRole role = getRole(rolename);
if (role != null) {
account.addObjectPermissions(role.getPermissions());
}
}
} else {
account.setRoles(null);
}

return account;
}
}


domingo, 29 de junio de 2014

Utilizando Apache Shiro para la seguridad en una aplicacion Web en Java

Como hemos visto en el post anterior, Apache Shiro es un  framework potente, ligero y fácil de usar que nos permite incorporar aspectos de seguridad a nuestras aplicaciones Java.


Para comenzar a utilizarlo deberás añadir las siguientes dependencias en el pom de tu proyecto.

<dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-core</artifactId>
      <version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
      <artifactId>shiro-web</artifactId>
      <version>1.2.2</version>
</dependency>

Un ServletFilter y un listener deben de ser registrados en el archivo web.xml. Estos serán usado por Shiro para interceptar todas las peticiones http a la aplicación y hacer una verificación de los permisos para el usuario actual. 


<listener>
<listener-class>
        org.apache.shiro.web.env.EnvironmentLoaderListener
</listener-class>
</listener>

 <filter>

    <filter-name>ShiroFilter</filter-name>
    <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>

<filter-mapping>

    <filter-name>ShiroFilter</filter-name>
    <url-pattern>/jsp/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>

Aunque Shiro nos ofrece diversas formas de definir nuestras reglas de auntentificación y autorización, en este ejemplo utilizaremos un archivo .ini. Esta variante es muy flexible pues como ya se ha dicho, permite declarar las reglas en un archivo externo a la aplicación, de una forma declarativa, haciendo que su modificación futura pueda ser realizada incluso sin realizar una recompilación.

En el archivo .ini. definiremos los usuarios, roles y permisos. También podremos controlar el acceso a cada una de las URL que referencien a páginas de nuestra aplicación, ya sea mediante roles o permisos que tambien pueden ser declarados aquí. Deberá de estar ubicado en algún lugar dentro del classpath de nuestra aplicación

A continuación veremos un definición de cada una de las secciones del mismo

[main]Configuración de los aspectos principales. 
Por ejemplo: La URL por defecto para las peticiones no autorizadas 
y la pagina a navegar por defecto.
authc.loginUrl = /jsp/login.xhtml
authc.successUrl = /jsp/index.xhtml

[users]-->Sección usada para asignar roles a los usuarios
admin=LECTOR
admin=EDITOR

[roles]----> Seccion para asignar permisos a los roles
LECTOR=nota:leer
EDITOR=nota:crear,modificar

[urls]----> Aqui se definen los permisos de cada URL de acuerdo a roles

que tenga el usuario actual, o a permisos que tengan uno de estos roles,
entre muchas otras posibilidades
/jsp/listaNotas.xhtml=perms["nota:leer"]
/jsp/insertarNota.xhtml=roles["EDITOR"]
/jsp/** = authc

Aunque la mayoría de los casos posibles de autorización quedan cubiertos en el archivo ini, algunas veces es necesario ir un poco mas lejos y restringir el acceso solo a determinados componentes dentro de una pagina y no a esta como un todo. Para conseguir esto Shiro posee la clase Subject que brinda detalles sobre el usuario actual y sus permisos a traves de métodos tales como isPermitted(String permiso) o isUserInRole(String role).

Armado con este pequeño mini tutorial es posible configurar nuestra primera aplicación para comenzar a usar el framework Apache Shiro. En proximas entradas contare como beneficiarse de su condición de framework open source y modificar su funcionalidad adaptandola a posibles situaciones, a traves de los multiples puntos de extension que posee.



domingo, 25 de mayo de 2014

Introducción a Apache Shiro

Apache Shiro es un framework escrito en el lenguaje Java pensado para ser usado en las tareas mas comunes relacionadas con la seguridad. Estas vendrían a ser Autenticación, Autorización, Encriptación y manejo de sesiones. Es un proyecto bastante maduro y estable y fue aceptado por la Apache Software Foundation en 2008 y ha sido un proyecto de primer nivel dentro de dicha fundación desde 2010.

Las características mas valorables que posee Shiro que lo hacen ser mas popular que los frameworks con los que compite en el panorama de seguridad (por ejemplo JAAS) para aplicaciones Java son:


  • Es simple y fácil de usar.
  • Fue concebido pensando en ser usado en aplicaciones Webs desde el inicio (JAAS por ejemplo comprende áreas tan especificas como la seguridad a nivel de maquina virtual lo que lo hacen mucho mas complejo )
  • Casi todos los aspectos de seguridad pueden ser definidos de manera declarativa en un archivo externo haciéndolo modificable incluso en aplicaciones desplegadas. Cuando la autorización se realiza programaticamente es basada en anotaciones en POJOS lo que hace que se necesite menos código de configuración
  • Las posibilidades que ofrece para declarar los aspectos de la autorización son muy especificas y flexibles a la vez. Permite Autorización basada en roles y permisos.
  • Brinda una capa de Manejo de Sesiones propia, solapando la que pudiese tener el contenedor de la aplicación. De igual forma Shiro soporta la clusterización de sesiones, de manera que si la sesión fuese propagada entre clusteres, la persistencia de los datos de sesión es manejada por el framework.
Hasta aquí esta corta introducción a Shiro. En un próximo post explicaré como comenzar a utilizarlo en un proyecto desde cero.