使用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 )