I get the user name in my JAX-RS resource with SecurityContextHolder
and that works:
@Path("/myresource")
public class MyResoure {
@Get
public String getUserName() {
return SecurityContextHolder.getContext().getAuthentication().getName();
}
}
But I want to inject the SecurityContext into a class field (to write JUnit tests). I tried some documented ways:
With javax.ws.rs.core.SecurityContext
I get a NullPointerException
, because the securityContext
is always null
.
@Path("/myresource")
public class MyResoure {
@Context
private javax.ws.rs.core.SecurityContext securityContext;
@Get
public String getUserName() {
return securityContext.getUserPrincipal().getName();
}
}
With org.apache.cxf.security.SecurityContext
(see Apache CXF documentation) I get a NullPointerException
, because the securityContext.getUserPrincipal()
is always null
.
@Path("/myresource")
public class MyResoure {
@Context
private org.apache.cxf.security.SecurityContext securityContext;
@Get
public String getUserName() {
return securityContext.getUserPrincipal().getName();
}
}
With org.apache.cxf.jaxrs.ext.MessageContext
(see Apache CXF documentation) I get a NullPointerException
, because the messageContext.getSecurityContext().getUserPrincipal()
is always null
.
@Path("/myresource")
public class MyResoure {
@Context
private org.apache.cxf.jaxrs.ext.MessageContext messageContext;
@Get
public String getUserName() {
return messageContext.getSecurityContext().getUserPrincipal().getName();
}
}
With javax.servlet.http.HttpServletRequest
I get a NullPointerException
, because the httpServletRequest.getUserPrincipal()
is always null
.
@Path("/myresource")
public class MyResoure {
@Context
private javax.servlet.http.HttpServletRequest httpServletRequest;
@Get
public String getUserName() {
return httpServletRequest.getUserPrincipal().getName();
}
To get the user name with
javax.ws.rs.core.SecurityContext
,
org.apache.cxf.security.SecurityContext
,
org.apache.cxf.jaxrs.ext.MessageContext
or
javax.servlet.http.HttpServletRequest
I had to add the SecurityContextHolderAwareRequestFilter
to my springSecurityFilterChain
.
Spring configuration:
<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
<security:filter-chain-map path-type="ant">
<security:filter-chain pattern="/**" filters="securityContextPersistenceFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor" />
</security:filter-chain-map>
</bean>
With Security Namespace Configuration or Java Configuration the filter is added by default, see Spring Security documentation:
- servlet-api-provision Provides versions of HttpServletRequest security methods such as isUserInRole() and getPrincipal() which are implemented by adding a SecurityContextHolderAwareRequestFilter bean to the stack. Defaults to true.
I found some solutions for my JUnit problem:
Setting SecurityContext
in SecurityContextHolder
(see https://stackoverflow.com/a/5703170)
JUnit test code:
public class MyResourceTest {
private SecurityContext securityContextMock = mock(SecurityContext.class);
@Before
public void setUp() {
SecurityContextHolder.setContext(securityContextMock);
}
@After
public void tearDown() {
SecurityContextHolder.clearContext();
}
}
Wrapping SecurityContextHolder
(see https://stackoverflow.com/a/5702970)
Wrapper code:
public class MySecurityContextHolder {
public SecurityContext getContext() {
return SecurityContextHolder.getContext();
}
}
Resource code:
@Path("/myresource")
public MyResource {
private MySecurityContextHolder mySecurityContextHolder;
@Get
public String getUserName() {
return mySecurityContextHolder.getContext().getAuthentication().getName();
}
}
Using SecurityContextHolderStrategy (see SEC-1188)
Spring configuration:
<bean id="myResource" class="MyResource">
<property name="securityContextHolderStrategy" >
<bean class="org.springframework.security.context.SecurityContextHolder" factory-method="getContexHolderStrategy">
</bean>
</property>
</bean>
Resource code:
@Path("/myresource")
public MyResource {
private SecurityContextHolderStrategy securityContextHolderStrategy;
@Get
public String getUserName() {
return securityContextHolderStrategy.getContext().getAuthentication().getName();
}
}
Using PowerMock (see https://stackoverflow.com/a/5703197/5277820)