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…