Spring. Decisiones de Control de Acceso

gerardo publicó esto el 11/03/10 en Java, Lenguajes de Programación. Un comentario

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:

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
     &amp;&amp; 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


Un comentario

Trackbacks and Pingbacks


Dejá un comentario

Imagen CAPTCHA CAPTCHA Audio
Refrescar imagen