davelt
davelt

Reputation: 69

Grails Spring Security Get Roles for the Current Page

I was wondering if anyone knows an elegant way to get all the roles in the spring security plugin that have access to the current page.

I am using spring security and it's configured to use RequestMap domain objects.

The permissions in my app are pretty complex so I wanted to make a tag at the bottom of each page displaying the roles need to use the page.

I was doing a query for the request map but I want to make sure the way I match the url is the same as the way the plugin does.

Ideally I wouldn't have to run a query at all.

Grails version 2.2.1 Spring Security Plugin version 1.2.7.3

Thanks in advance

Upvotes: 2

Views: 298

Answers (1)

davelt
davelt

Reputation: 69

I got this to work by adding the following two classes to my src/java.

Class 1

import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

import javax.servlet.http.HttpServletRequest;
import java.util.Collection;

public class MyFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

FilterInvocationSecurityMetadataSource oldBean;

@Override
public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
    FilterInvocation filterInvocation = (FilterInvocation) o;
    HttpServletRequest request = filterInvocation.getHttpRequest();
    request.setAttribute("PAGEROLES", oldBean.getAttributes(filterInvocation));

    return oldBean.getAttributes(o);
}

@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
    return oldBean.getAllConfigAttributes();
}

@Override
public boolean supports(Class<?> aClass) {
    return FilterInvocation.class.isAssignableFrom(aClass);
}

public Object getOldBean() { return oldBean; }
public void setOldBean(FilterInvocationSecurityMetadataSource oldBean) { this.oldBean = oldBean; }
}

Class 2

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

public class FilterSecurityMDSExtractor implements BeanPostProcessor, BeanFactoryAware {
    private ConfigurableListableBeanFactory bf;
    private FilterInvocationSecurityMetadataSource metadataSource = new MyFilterInvocationSecurityMetadataSource();

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof FilterInvocationSecurityMetadataSource) {
            ((MyFilterInvocationSecurityMetadataSource) metadataSource).setOldBean((FilterInvocationSecurityMetadataSource) bean);
            return metadataSource;
        }
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.bf = (ConfigurableListableBeanFactory)beanFactory;
    }
}

I then added the following to resources.groovy

beans = {
      filterSecurityMDSExtractor(FilterSecurityMDSExtractor)
}

Basically I am stuffing the user roles into the request

request.setAttribute("PAGEROLES", oldBean.getAttributes(filterInvocation));

then all I have to do is call the following

request.getAttribute("PAGEROLES");

to get the roles back out. I pieced together my solution by stealing from other great posts on Stackoverflow. Someone else might have a better solution but so far this is working for me.

Upvotes: 2

Related Questions