Interview Questions

Spring Security - Role based Url Authorization

It is a common aspect in a web application, to have a User Group management module, which is used to create users, groups, roles and also assign roles to users. Adding roles to Users, provides access restriction to that particular module at a logical level but not at the URL level.

For example, if a user is not allowed to view certain web pages in a module, usually that particular links will not be shown to user in the menu (or sub menu). At the same time the user should not be allowed access, when he tries to directly access the URL from browser.

This can be achieved using the following API class in Spring Security framework.

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

public class CommonFilterSecurityMetaDataSource implements FilterInvocationSecurityMetadataSource
{
        public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException
        {
                FilterInvocation fI = (FilterInvocation) object;
                Object principal = null;
                if(SecurityContextHolder.getContext().getAuthentication()==null || SecurityContextHolder.getContext().getAuthentication().getPrincipal()==null)
                {
                        throw new AuthenticationCredentialsNotFoundException("An Authentication object was not found in the SecurityContext");
                }
                else
                {
                principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
                }

                //to strip of query string from url.
            String url = fI.getRequestUrl();
            if(url.indexOf('?')!=-1)
            url = url.substring(0, url.indexOf('?'));
            url = url.trim();
           
            List<ConfigAttribute> attributes = new ArrayList<ConfigAttribute>();
            User user = (User)principal;
               
                //This is sample code for role based url access.
                //Here the user bean contains a set of tasks with urls. We are comparing the current url with the set of urls
                // allowed for this user .
                //Please provide your own code as per your requirement.
                /*  for(Task roleBasedUrls:user.getTasks())
                    {
                         if(StringUtils.isNotEmpty(roleBasedUrls.getUrl()) && (roleBasedUrls.getUrl().toLowerCase()).contains(url.toLowerCase()))
                         {
                                 attributes.add(new SecurityConfig("IS_AUTHENTICATED_FULLY"));
                                 break;
                         }
                    }
           */

          if(attributes.isEmpty())
          {
                  attributes.add(new SecurityConfig("IS_NOT_AUTHENTICATED_FULLY"));
          }
                return attributes;
        }
        public Collection<ConfigAttribute> getAllConfigAttributes()
        {
                return null;
        }
        public boolean supports(Class<?> clazz)
        {
                return true;
        }
}

Please follow the Spring Security Configuration article, for bean configuration.

Additionally you need to define the bean configuration for the above class as follows.

<beans:bean id="filterSecurityMetadataSource" class="in.techdive.web.CommonFilterSecurityMetaDataSource">
</beans:bean>