In the previous part we looked how to secure the URL calls. Now let us look into how to secure the method invocation. Let us again have a properties file (methods.properties) that contains the method names and the roles that can invoke the methods. For example,
com.test.service.MyService.delete*=ROLE_USER,ROLE_MANAGER
com.test.service.MyService.createAccount=ROLE_ADMIN
You can also have this mapping defined in database or LDAP server. For simplicity we will have the mapping defined in a properties file.
Let us now define interface (IMyService) and implementation (MyService)
public interface IMyService {
public void deleteUserPreferences (String userName);
public void deleteUserLogs(String userName);
public void createAccount(String userName);
}
Now based on the above configurations ROLE_USER, ROLE_MANAGER would only be able to invoke the methods deleteUserPreferences and deleteUserLogs. ROLE_ADMIN would only be able to invoke method createAccount.
Now you can write MyService implementing the above interface.
Method security in enforced using a MethodSecurityInterceptor, which secures
MethodInvocations. The interceptor uses a MethodDefinitionSource instance to obtain the configuration attributes that apply to a particular method invocation. Since we would be reading the methods names and the corresponding roles from properties file, we would either –
1. Define our own implementation of MethodSecurityMetadataSource and implement all methods.
2. Or we can write a class extending MapBasedMethodSecurityMetadataSource. MapBasedMethodDefinitionSource is used to store configuration attributes keyed by method names (which can be wildcarded) and will be used internally when the attributes are defined in the application context using the <intercept-methods> or <protect-point> elements.
We will go ahead with point 2 as we just need to read the properties file, create Map<String, List<ConfigAttribute>> and call MapBasedMethodDefinitionSource’s constructor passing this map.
So, let us first define a bean PropertyHolder that would read the properties file and create Map<String, List<ConfigAttribute>>.
<bean id="propHolder" class="com.test.common.PropertyHolder">
<property name="methodProperties">
<util:properties location="classpath:methods.properties" />
</property>
</bean>
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.util.StringUtils;
public class PropertyHolder {
private Properties methodProperties;
public void setMethodProperties(Properties methodProperties) {
this.methodProperties = methodProperties;
}
public Properties getMethodProperties() {
return methodProperties;
}
public Map<String, List<ConfigAttribute>> getMethodMap() {
Map<String, List<ConfigAttribute>> methodMap = new HashMap<String, List<ConfigAttribute>>();
for (Iterator iter = methodProperties.keySet().iterator(); iter
.hasNext();) {
String name = (String) iter.next();
String value = methodProperties.getProperty(name);
String[] tokens = StringUtils
.commaDelimitedListToStringArray(value);
List<ConfigAttribute> attributes = new ArrayList<ConfigAttribute>(
tokens.length);
for (String token : tokens) {
attributes.add(new SecurityConfig(token));
}
methodMap.put(name, attributes);
}
return methodMap;
}
}
Now let us configure a MethodSecurityIterceptor in our application context
<bean id="methodSecurityInterceptor" class="org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="securityMetadataSource" ref="mySecurityMetadataSource"/>
</bean>
We have already configured authenticationManager and accessDecisionManager in previous parts.
Let us now configure mySecurityMetadataSource.
<bean id=" mySecurityMetadataSource" class="com.test.common.MySecurityMetadataSource">
<constructor-arg name="propHolder" ref="propHolder"/>
</bean>
Now let us write the bean MySecurityMetadataSource that extends MapBasedMethodSecurityMetadataSource.
Import org.springframework.security.access.method.MapBasedMethodSecurityMetadataSource;
public class MySecurityMetadataSource extends
MapBasedMethodSecurityMetadataSource {
public MyMethodSecurityFilterNew(PropertyHolder propHolder) {
super(propHolder.getMethodMap());
}
}
Now define the beans MyService in application context that we want to secure and define another bean org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator to create a proxy for MyService object so that an authorization check may be applied for every invocation on the object.
<bean id=”myService” class=”com.test.service.MyService” />
<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="interceptorNames">
<list>
<value>methodSecurityInterceptor</value>
</list>
</property>
<property name="beanNames">
<list>
<value> myService</value>
</list>
</property>
</bean>
Showing posts with label Role based Method Invocation. Show all posts
Showing posts with label Role based Method Invocation. Show all posts
Sunday, January 3, 2010
Subscribe to:
Posts (Atom)