问题
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();
}
回答1:
To get the user name with
javax.ws.rs.core.SecurityContext
,org.apache.cxf.security.SecurityContext
,org.apache.cxf.jaxrs.ext.MessageContext
orjavax.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.
回答2:
I found some solutions for my JUnit problem:
Setting
SecurityContext
inSecurityContextHolder
(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)
来源:https://stackoverflow.com/questions/32796368/get-user-name-with-apache-cxf-2-4-jax-rs-and-spring-security-3-2