Spring. Decisiones de Control de Acceso
Marzo 11th, 2010
En el proceso de autenticación, una aplicación permitirá a usuarios autenticados una serie de servicios permitidos. Cuando este usuario intenta acceder a un recurso en la aplicacion, tiene que tomar la decisión sobre qué recursos son accesibles con los permisos que tiene asignados o con otras características.
La decisión si a determinado usuario se le permite acceder a un recurso dentro de la aplicación se llama “decisión de control de acceso”. Se basa en el estado de la autenticación del usuario, y de la naturaleza de los recursos y los atributos de acceso. En Spring security, las decisiones de control de acceso son llevados a cabo por los managers de decisión de acceso, los cuales deben implementar la interfaz AccessDecisionManager. Cada uno es libre de crear su propio manager de decisión de acceso implementando esta interfaz, de todas maneras Spring Security viene con tres managers que implementan esta interfaz basado en el método de votos.
| Método de Manager de Decisión de Acceso | Cuando conceder acceso |
|---|---|
| AffirmativeBased | Al menos un votante vota para conceder acceso |
| ConsensusBased | Un concenso de vontantes para conceder acceso |
| UnanimousBased | Todos los votantes votan o se abstienen para conceder acceso, ninguno vota por denegar el accesos |
Todos estos managers de decision requieren un grupo de vontantes que se configuran para la votación sobre las decisiones de control de acceso. Cada votante debe implementar la interfaz AccessDecisionVoter. Un votante puede votar para garantizar el acceso, puede abstenerse de votar o puede denegar un recurso. Los resultados se representan por las constantes ACCESS_GRANTED, ACCESS_DENIED, y ACCESS_ABSTAIN que son definidos en la interfaz AccessDecisionVoter.
Por defecto si no se especifica ningún manager de decision de acceso entonces Spring va a configurar automaticamente un manager con el método AffirmativeBased con los dos siguientes votantes:
- RoleVoter: vota por una decision de control de accesos basando en el rol del usuario. Solamente procesará los atributos de acceso que contengan el prefijo ROLE_, pero este prefijo se puede configurar. Vota por garantizar el acceso si el usuario tiene el mismo rol que el requerido para accedejor al recurso. vota por denegar el acceso si el usuario carece del rol requerido. Si el recurso no tiene un atributo de acceso que comienza con el prefijo ROLE_, el vontante se abstendra de emitir su voto.
- AuthenticatedVoter: vota por una decision de control de acceso basado en niveles de autenticación de usuario. solamente procesará si el atributo de acceso es IS_AUTHENTICATED_FULLY, IS_AUTHENTICATED_REMEMBERED, and IS_AUTHENTICATED_ANONYMOUSLY. Votará afirmativamente si el nivel de autenticacion es superior que el atributo requerido. De arriba para abajo los niveles de autenticacion son: “fully authenticated,” “authentication remembered,” y “anonymously authenticated.”
Por defecto, Spring security configurará un manager de decisión de acceso si no se especifica alguno. Este managaer de decision de acceso por defecto es equivalente al definido en la siguiente configuración:
<bean id="_accessManager"> <property name="decisionVoters"> <list> <bean class=org.springframework.security.vote.RoleVoter/> <bean class=org.springframework.security.vote.AuthenticatedVoter/> </list> </property> </bean>
Este manager de decision de acceso y su s votantes deberian satisfacer los requerimientos tipicos de autenticacion. No obstante, si no satisface alguno específico, se puede crear uno propio. En la mayoria de los casos, se necesitará crear un votante customizado. Por ejemplo, se puede crear un votante que tome decision en base a la direccion IP del usuario:
package com.apress.springrecipes.board.security; import org.springframework.security.Authentication; import org.springframework.security.ConfigAttribute; import org.springframework.security.ConfigAttributeDefinition; import org.springframework.security.ui.WebAuthenticationDetails; public class IpAddressVoter implements AccessDecisionVoter { public static final String IP_PREFIX = "IP_"; public static final String IP_LOCAL_HOST = "IP_LOCAL_HOST"; public boolean supports(ConfigAttribute attribute) { return attribute.getAttribute() != null && attribute.getAttribute().startsWith(IP_PREFIX); } public boolean supports(Class clazz) { return true; } public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) { if (!(authentication.getDetails() instanceof WebAuthenticationDetails)) { return ACCESS_DENIED; } WebAuthenticationDetails details = (WebAuthenticationDetails) authentication.getDetails(); String address = details.getRemoteAddress(); int result = ACCESS_ABSTAIN; for (Object element : config.getConfigAttributes()) { ConfigAttribute attribute = (ConfigAttribute) element; if (this.supports(attribute)) { result = ACCESS_DENIED; if (IP_LOCAL_HOST.equals(attribute.getAttribute())) { if (address.equals("127.0.0.1")) { return ACCESS_GRANTED; } } } } return result; } }
Notar que este vontante procesará los atrbutos de acceso que comienzan con el prefijo IP_. Por el momento, solamente soporta el atributo IP_LOCAL_HOST. Su el usuario es un cliente web cuya direcciones IP es iguial a 127.0.0.1, votará por un acceso permitido. De otra forma, votará por denmegar el acceso. Si el recurso no tiene un atributo que comienza con IP_, entonces se abstine de votar.
A continuación habra que definir un manager de decision de acceso personalizado que incluya este votante:
<beans:bean id=”accessDecisionManager” class=”org.springframework.security.vote.AffirmativeBased”> <beans:property name=”decisionVoters”> <beans:list> <beans:bean class=”org.springframework.security.vote.RoleVoter” /> <beans:bean class=”org.springframework.security.vote.AuthenticatedVoter” /> <beans:bean class=”com.apress.springrecipes.board.security.IpAddressVoter” /> </beans:list> </beans:property> </beans:bean>
Ahora supongamos que nos gustaría permitir usuarios de maquinas que corren un container WEB. Habra que hacer referencia a este manager de decision de acceso desde el elemento de configuracion <http> para agregar el atributo de acceso IP_LOCAL_HOST a la url /messageDelete-htm*:
<http access-decision-manager-ref=”accessDecisionManager”> <intercept-url pattern=”/messageList.htm*” access=”ROLE_USER,ROLE_GUEST” /> <intercept-url pattern=”/messagePost.htm*” access=”ROLE_USER” /> <intercept-url pattern=”/messageDelete.htm*” access=”ROLE_ADMIN,IP_LOCAL_HOST” /> … </http>
Entonces si se quiere acceder a la aplicacion board message desde localhost, no se necesitará loguearse como administrador para ejecutar la acción.
Traducido de Apress Spring Recipes A Problem-Solution Approach (2008) - Gary Mak



Leave a Reply