问题
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.MessageContextorjavax.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
SecurityContextinSecurityContextHolder(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