【问题标题】:Injecting SecurityContextHolder via Autowired通过 Autowired 注入 SecurityContextHolder
【发布时间】:2017-06-30 12:18:35
【问题描述】:

我想使用 Spring-AOP 记录我的请求信息。之后我想用测试来覆盖这个场景。通常我会简单地使用SecurityContextHolder,但由于我的单元测试中没有弹簧上下文,我需要以某种方式模拟这个元素。由于我想避免模拟私有方法,因此我通过Autowired 注释传递了SecurityContextHolder,因此无论如何我都希望这是一个单例。

@PrepareForTest(SecurityContextHolder.class)
public class AuditLoggerTest extends PowerMockTestCase {

  @Mock
  AuditLogPersistenceService persistenceService;

  @Mock
  SecurityContextHolder securityContextHolder;

  @Mock
  SecurityContext securityContext;

  @Mock
  Authentication authentication;

  AuditLogger auditLogger;

  @BeforeClass
  public void setUp() {
    MockitoAnnotations.initMocks(this);
  }

  @BeforeMethod
  public void setUpBeforeEachTest(){
    auditLogger = new AuditLogger(persistenceService, securityContextHolder);
    Object principal = new String("123");
    PowerMockito.mockStatic(SecurityContextHolder.class);
    when(securityContextHolder.getContext()).thenReturn(securityContext);
    when(securityContext.getAuthentication()).thenReturn(authentication);
    when(authentication.getPrincipal()).thenReturn(principal);
  }

现在我的类的初始化看起来像这样

@Aspect
@Component
public class AuditLogger {

  private final AuditLogPersistenceService auditLogPersistenceService;

  private final SecurityContextHolder securityContextHolder;

  /**
   * Common constructor raising its beans
   * @param auditLogPersistenceService
   */
  @Autowired
  public AuditLogger(
      final AuditLogPersistenceService auditLogPersistenceService,
      final SecurityContextHolder securityContextHolder) {
    this.securityContextHolder = securityContextHolder;
    this.auditLogPersistenceService = auditLogPersistenceService;
  }

它在单元测试中运行良好,但是一旦我在我的功能测试中打开 Spring 上下文,它实际上通过再保证执行 REST 请求。我收到此错误消息。

Parameter 1 of constructor in com.service.audit.logging.AuditLogger required a bean of type 'org.springframework.security.core.context.SecurityContextHolder' that could not be found.

Consider defining a bean of type 'org.springframework.security.core.context.SecurityContextHolder' in your configuration.

那么我可以自动装配 SecurityContextHolder 还是必须使用静态实现?

【问题讨论】:

  • 你可以自动接线,但这听起来不像是要走的路。此外,安全上下文绝对不是单例。通常,您会注入请求上下文并从请求中访问安全上下文(安全上下文通常是请求范围的)。在身份验证和创建安全上下文之后,您将在请求中设置该上下文。您可以为此实现提供者机制,该机制也可以为您注入请求范围的安全上下文。

标签: spring spring-boot spring-security spring-aop


【解决方案1】:

总之,最简单的方法是将模拟的上下文注入SecurityContextHolder,就像这样。然后 SecurityContextHolder 不在构造函数中了

public class AuditLoggerTest extends PowerMockTestCase {

      @Mock
      AuditLogPersistenceService persistenceService;

      @Mock
      SecurityContext securityContext;

      @Mock
      Authentication authentication;


      AuditLogger auditLogger;


      @BeforeClass
      public void setUp() {
        MockitoAnnotations.initMocks(this);
      }

      @BeforeMethod
      public void setUpBeforeTest(){
        auditLogger = new AuditLogger(persistenceService);
        SecurityContextHolder.setContext(securityContext);
        Object principal = new String("123");
        when(securityContext.getAuthentication()).thenReturn(authentication);
        when(authentication.getPrincipal()).thenReturn(principal);
      }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-29
    • 1970-01-01
    相关资源
    最近更新 更多