Enterprise Architect in HCL Technologies a $7Billion IT services organization. My role is to work as a Technology Partner for large enterprise customers providing them low cost opensource solutions around Java, Spring and vFabric stack. I am also working on various projects involving, Cloud base solution, Mobile application and Business Analytics around Spring and vFabric space. Over 23 yrs, I have build repository of technologies and tools I liked and used extensively in my day to day work. In this blog, I am putting all these best practices and tools so that it will help the people who visit my website. Krishna is a DZone MVB and is not an employee of DZone and has posted 64 posts at DZone. You can read more from them at their website. View Full User Profile

Spring-Test-MVC Junit Testing Spring Security Layer with Method Level Security

02.21.2013
| 5925 views |
  • submit to reddit

For people in hurry get the code from Github.

In continuation of my earlier blog on spring-test-mvc junit testing Spring Security layer with InMemoryDaoImpl, in this blog I will discuss how to use achieve method level access control. Please follow the steps in this blog to setup spring-test-mvc and run the below test case.

mvn test -Dtest=com.example.springsecurity.web.controllers.SecurityControllerTest

The JUnit test case looks as below,

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = WebContextLoader.class, value = { "classpath:/META-INF/spring/services.xml",
"classpath:/META-INF/spring/security.xml",
"classpath:/META-INF/spring/mvc-config.xml" })
public class SecurityControllerTest {

@Autowired
CalendarService calendarService;

@Test
public void testMyEvents() throws Exception {
Authentication auth = new UsernamePasswordAuthenticationToken("user1@example.com", "user1");
SecurityContext securityContext = SecurityContextHolder.getContext();
securityContext.setAuthentication(auth);

calendarService.findForUser(0);
SecurityContextHolder.clearContext();
}

@Test(expected = AuthenticationCredentialsNotFoundException.class)
public void testForbiddenEvents() throws Exception {
calendarService.findForUser(0);
}
}
@Test(expected=AccessDeniedException.class)
public void testWrongUserEvents() throws Exception {
Authentication auth = new UsernamePasswordAuthenticationToken("user2@example.com", "user2");
SecurityContext securityContext = SecurityContextHolder.getContext();
securityContext.setAuthentication(auth);

calendarService.findForUser(0);
SecurityContextHolder.clearContext();
}

If you notice, if the user did not login or if the user is trying to access another users information it will throw an exception.

The interface access control is as below,

public interface CalendarService {

@PreAuthorize("hasRole('ROLE_ADMIN') or principal.id == #userId")
List<Event> findForUser(int userId);
}

The PreAuthorize only works on interface so that any implementation that implements this interface has this access control.

I hope this blog helps you.


 

Published at DZone with permission of Krishna Prasad, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)