This article is participating in “Java Theme Month – Java Debug Notes Event”, see < Event link > for more details.

Question: when using springsecurity, what is the correct way to get information about the current user name (that is, SecurityContext) in the bean?

I have a springmvcweb application that uses springsecurity. I want to know the user name of the current logged-in user. Can I use the code snippet given below?

I don’t like to call a static method in this controller — it breaks all of Spring’s functionality. Is there a way to inject the application configuration into the current SecurityContext or current authentication?

@RequestMapping(method = RequestMethod.GET)
public ModelAndView showResults(final HttpServletRequest request...) {
finalString currentUser = SecurityContextHolder.getContext().getAuthentication().getName(); . }Copy the code

Answer a

If you’re using Spring3, the easiest way to do this is:

 @RequestMapping(method = RequestMethod.GET)   
 public ModelAndView showResults(final HttpServletRequest request, Principal principal) {

     final String currentUser = principal.getName();

 }
Copy the code

Answer two

Much has changed in the Spring world since this question was answered. Spring simplifies the process of getting the current user in the controller. For other beans, Spring takes the author’s advice and simplifies the injection of SecurityContextHolder.

This is the solution I ultimately chose. Instead of using SecurityContextHolder in my controller, I want to inject something that uses SecurityContextHolder, but abstracts the singleton-like class from my code. I found that there was no other way to do this than to change my interface, such as:

public interface SecurityContextFacade {

  SecurityContext getContext(a);

  void setContext(SecurityContext securityContext);

}
Copy the code

Now my controller is written like this:

public class FooController {

  private final SecurityContextFacade securityContextFacade;

  public FooController(SecurityContextFacade securityContextFacade) {
    this.securityContextFacade = securityContextFacade;
  }

  public void doSomething(a){
    SecurityContext context = securityContextFacade.getContext();
    // do something w/ context}}Copy the code

And because the interface is a decoupling point, unit testing is simple. In this example, I use Mockito:

public class FooControllerTest {

  private FooController controller;
  private SecurityContextFacade mockSecurityContextFacade;
  private SecurityContext mockSecurityContext;

  @Before
  public void setUp(a) throws Exception {
    mockSecurityContextFacade = mock(SecurityContextFacade.class);
    mockSecurityContext = mock(SecurityContext.class);
    stub(mockSecurityContextFacade.getContext()).toReturn(mockSecurityContext);
    controller = new FooController(mockSecurityContextFacade);
  }

  @Test
  public void testDoSomething(a) { controller.doSomething(); verify(mockSecurityContextFacade).getContext(); }}Copy the code

The default implementation of the interface is as follows:

public class SecurityContextHolderFacade implements SecurityContextFacade {

  public SecurityContext getContext(a) {
    return SecurityContextHolder.getContext();
  }

  public void setContext(SecurityContext securityContext) { SecurityContextHolder.setContext(securityContext); }}Copy the code

Finally, the Spring configuration looks like this:

<bean id="myController" class="com.foo.FooController">... <constructor-arg index="1">
    <bean class="com.foo.SecurityContextHolderFacade">
  </constructor-arg>
</bean>
Copy the code

The article translated from Stack Overflow:stackoverflow.com/questions/2…