Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Having trouble injecting my Spring security user into my controller

I'm using Spring 3.1.0.RELEASE with Spring Security 3.1. I want to inject my Spring user (i.e. the user who is currently logged in) into a controller. I want to do this as opposed to using

SecurityContextHolder.getContext().getAuthentication().getPrincipal();

because it allows me to test the controller more easily with JUnit. However, I'm having a problem with my current setup. My question is, what is the correct way to inject my user (per request) into my controller? In my application context file, I have ...

<bean id="userDetails" class="com.myco.eventmaven.security.SecurityHolder" factory-method="getUserDetails" scope="request">
    <aop:scoped-proxy />
</bean>

where I define my factory class as ...

public class SecurityHolder {

@Autowired
private static UserService userService;

public static MyUserDetails getUserDetails() {
    final Authentication a = SecurityContextHolder.getContext().getAuthentication();
    if (a == null) {
        return null;
    } else {
        final MyUserDetails reg = (MyUserDetails) a.getPrincipal();
        final int userId = reg.getId();
        final MyUserDetails foundUser = userService.findUserById(userId);
        return foundUser;
    } // if
}   // getUserDetails

}

but the factory class repeatedly dies because "userService" fails to get autowired (the value is always null). I'm looking for a better way to do all this that can easily also integrate into my JUnit test. Any ideas?

Edit: Here's the JUnit test I'm looking to work with ...

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "file:src/test/resources/testApplicationContext.xml" })
public class UserEventFeedsControllerTest extends AbstractTransactionalJUnit4SpringContextTests {

private MockHttpServletRequest request;
private MockHttpServletResponse response;
...
@Autowired
private RequestMappingHandlerAdapter handlerAdapter;

@Autowired
private RequestMappingHandlerMapping handlerMapping;

@Before
public void setUp() {
    ...
    request = new MockHttpServletRequest();
    response = new MockHttpServletResponse();
}
...
@Test
public void testSubmitUserEventFeedsForm() throws Exception {
    request.setRequestURI("/eventfeeds.jsp");
    request.setMethod("POST");
    final List<EventFeed> allEventFeeds = getAllEventFeeds();
    request.setParameter("userEventFeeds", allEventFeeds.get(0).getId().toString());

    final Object handler = handlerMapping.getHandler(request).getHandler();
    final ModelAndView mav = handlerAdapter.handle(request, response, handler);

    assertViewName(mav, "user/eventfeeds");
}
like image 606
Dave Avatar asked Mar 20 '12 19:03

Dave


People also ask

How do you authenticate Spring Security?

A common way to authenticate users is by requiring the user to enter a username and password. Once authentication is performed we know the identity and can perform authorization. Spring Security provides built in support for authenticating users.

What is authentication entry point in Spring Security?

AuthenticationEntryPoint is used in Spring Web Security to configure an application to perform certain actions whenever an unauthenticated client tries to access private resources.


1 Answers

You cannot autowire static fields. There are some workarounds, but I don't want to show them to you...

There are plenty of ways to access current user in an easier and more elegant matter:

  • Inject Principal to your controller (see When using Spring Security, what is the proper way to obtain current username (i.e. SecurityContext) information in a bean?):

    public ModelAndView showResults(final HttpServletRequest request, Principal principal) {
      final String currentUser = principal.getName();
      UserDetails ud = ((Authentication)principal).getPrincipal()
    
  • Develop your custom facade over SecurityContext

  • Replace built-in contextHolderStrategy in SecurityContextHolder for the purpose of testing

See also

  • How to get active user's UserDetails
  • Spring 3 MVC Controller integration test - inject Principal into method
like image 135
Tomasz Nurkiewicz Avatar answered Oct 11 '22 18:10

Tomasz Nurkiewicz