使用Apache CXF 2.4 JAX-RS和Spring Security 3.2获取用户名

我使用SecurityContextHolder在我的JAX-RS资源中获取用户名,并且可以正常工作:

 @Path("/myresource") public class MyResoure { @Get public String getUserName() { return SecurityContextHolder.getContext().getAuthentication().getName(); } } 

但我想将SecurityContext注入到类字段中(以编写JUnit测试)。 我尝试了一些记录的方法:

使用javax.ws.rs.core.SecurityContext我得到一个NullPointerException ,因为securityContext始终为null

 @Path("/myresource") public class MyResoure { @Context private javax.ws.rs.core.SecurityContext securityContext; @Get public String getUserName() { return securityContext.getUserPrincipal().getName(); } } 

使用org.apache.cxf.security.SecurityContext (请参阅Apache CXF文档 ),我得到一个NullPointerException ,因为securityContext.getUserPrincipal()始终为null

 @Path("/myresource") public class MyResoure { @Context private org.apache.cxf.security.SecurityContext securityContext; @Get public String getUserName() { return securityContext.getUserPrincipal().getName(); } } 

使用org.apache.cxf.jaxrs.ext.MessageContext (请参阅Apache CXF文档 ),我得到一个NullPointerException ,因为messageContext.getSecurityContext().getUserPrincipal()始终为null

 @Path("/myresource") public class MyResoure { @Context private org.apache.cxf.jaxrs.ext.MessageContext messageContext; @Get public String getUserName() { return messageContext.getSecurityContext().getUserPrincipal().getName(); } } 

使用javax.servlet.http.HttpServletRequest我得到一个NullPointerException ,因为httpServletRequest.getUserPrincipal()始终为null

 @Path("/myresource") public class MyResoure { @Context private javax.servlet.http.HttpServletRequest httpServletRequest; @Get public String getUserName() { return httpServletRequest.getUserPrincipal().getName(); } 

获取用户名

  • javax.ws.rs.core.SecurityContext
  • org.apache.cxf.security.SecurityContext
  • org.apache.cxf.jaxrs.ext.MessageContext
  • javax.servlet.http.HttpServletRequest

我不得不将SecurityContextHolderAwareRequestFilter添加到我的springSecurityFilterChain

弹簧配置:

      

使用安全命名空间配置或Java配置 ,默认情况下会添加filter,请参阅Spring Security文档 :

  • servlet-api-provision提供HttpServletRequest安全方法的版本,例如isUserInRole()和getPrincipal(),它们通过向堆栈添加SecurityContextHolderAwareRequestFilter bean来实现。 默认为true。

我找到了一些解决JUnit问题的方法:

  • SecurityContextHolder设置SecurityContext (请参阅https://stackoverflow.com/a/5703170 )

    JUnit测试代码:

     public class MyResourceTest { private SecurityContext securityContextMock = mock(SecurityContext.class); @Before public void setUp() { SecurityContextHolder.setContext(securityContextMock); } @After public void tearDown() { SecurityContextHolder.clearContext(); } } 
  • 包装SecurityContextHolder (参见https://stackoverflow.com/a/5702970 )

    包装代码:

     public class MySecurityContextHolder { public SecurityContext getContext() { return SecurityContextHolder.getContext(); } } 

    资源代码:

     @Path("/myresource") public MyResource { private MySecurityContextHolder mySecurityContextHolder; @Get public String getUserName() { return mySecurityContextHolder.getContext().getAuthentication().getName(); } } 
  • 使用SecurityContextHolderStrategy(参见SEC-1188 )

    弹簧配置:

           

    资源代码:

     @Path("/myresource") public MyResource { private SecurityContextHolderStrategy securityContextHolderStrategy; @Get public String getUserName() { return securityContextHolderStrategy.getContext().getAuthentication().getName(); } } 
  • 使用PowerMock(请参阅https://stackoverflow.com/a/5703197/5277820 )