【问题标题】:Simulate Anonymous Authentication in Spring MVC Unit Test在 Spring MVC 单元测试中模拟匿名身份验证
【发布时间】:2016-04-04 00:21:25
【问题描述】:

我正在尝试为来宾用户帐户编写单元测试。被测代码通过调用此方法检查来宾,在单元测试中为来宾帐户返回 null。

/**
 * Determines if the user is a guest account.
 *
 * @return True if the account is guest account, false otherwise.
 */
public boolean isGuest() {
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    if (auth != null) {
        if (auth instanceof AnonymousAuthenticationToken) {
            return true;
        } else {
            return false;
        }
    } else {
        return false;
    }
}

在服务器 Tomcat 容器中,匿名用户是可以的,它返回一个 AnonymousAuthenticationToken 的实例。因为容器环境和单元测试环境都共享同一个安全配置类,假设安全配置可能是正确的。

下面的测试代码也适用于MockUser,所以我也认为安全测试配置可能没问题:

@Test
@WithMockUser(username="Test.Customer.1@mailinator.com", roles = {"ADMIN"})
public void testCheckoutPage() throws Exception{
    logger.entry();
    String targetView = OrderViews.convertViewReference(getPageDirectory(), OrderViews.CHECKOUT_LOGIN_PAGE, false);
    String targetUrl = "/checkout";

    Order order = OrderBuilder.buildSampleGuestOrder(OrderStatus.NEW, 5);
    prepareMocks(order);
    Map<String, Object> sessionAttrs = new HashMap<>();
    sessionAttrs.put(OrderConstants.OPEN_ORDER_ID_ATTRIBUTE, order.getId());

    this.mockMvc.perform(get(targetUrl).sessionAttrs(sessionAttrs))
            .andExpect(status().isOk())
            .andExpect(view().name(targetView))
            .andExpect(model().attribute("order", order))
            .andExpect(model().attributeExists("loginForm"));


    this.mockMvc.perform(MockMvcRequestBuilders.post(targetUrl))
            .andExpect(status().isMethodNotAllowed());

    logger.exit();
}

有人知道如何在单元测试中模拟匿名身份验证令牌吗?

【问题讨论】:

    标签: spring-security spring-test spring-test-mvc


    【解决方案1】:

    在运行测试之前设置身份验证

    @Before
    public void setupAuthentication(){
        SecurityContextHolder.getContext().setAuthentication(new AnonymousAuthenticationToken("GUEST","USERNAME", AuthorityUtils
                .createAuthorityList("ROLE_ONE", "ROLE_TWO")));
    }
    

    【讨论】:

      【解决方案2】:

      在 Spring Security 4.1(尚未 GA)中,我们引入了对 @WithAnonymousUser 的支持。

      @WithAnonymousUser 支持是使用 @WithSecurityContext 构建的。这意味着您可以轻松地将支持添加到 4.0.x 中的代码库,直到 4.1.x 发布。要让它工作,您需要将以下类复制到您的测试源文件夹:

      package org.springframework.security.test.context.support;
      
      import java.lang.annotation.Documented;
      import java.lang.annotation.ElementType;
      import java.lang.annotation.Inherited;
      import java.lang.annotation.Retention;
      import java.lang.annotation.RetentionPolicy;
      import java.lang.annotation.Target;
      
      import org.springframework.security.authentication.AnonymousAuthenticationToken;
      import org.springframework.security.core.context.SecurityContext;
      
      @Target({ ElementType.METHOD, ElementType.TYPE })
      @Retention(RetentionPolicy.RUNTIME)
      @Inherited
      @Documented
      @WithSecurityContext(factory = WithAnonymousUserSecurityContextFactory.class)
      public @interface WithAnonymousUser {}
      
      package org.springframework.security.test.context.support;
      
      import java.util.List;
      
      import org.springframework.security.authentication.AnonymousAuthenticationToken;
      import org.springframework.security.core.Authentication;
      import org.springframework.security.core.GrantedAuthority;
      import org.springframework.security.core.authority.AuthorityUtils;
      import org.springframework.security.core.context.SecurityContext;
      import org.springframework.security.core.context.SecurityContextHolder;
      
      final class WithAnonymousUserSecurityContextFactory implements
              WithSecurityContextFactory<WithAnonymousUser> {
      
          public SecurityContext createSecurityContext(WithAnonymousUser withUser) {
              List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS");
              Authentication authentication = new AnonymousAuthenticationToken("key", "anonymous", authorities);
              SecurityContext context = SecurityContextHolder.createEmptyContext();
              context.setAuthentication(authentication);
              return context;
          }
      }
      

      那么你就可以使用下面的方式以匿名用户身份运行了:

      @Test
      @WithAnonymousUser
      public void testAnonymous() throws Exception {
          // ...
      }
      

      注意:重要的是要注意,就像您需要为 @WithMockUser 执行的操作一样,您需要确保将 MockMvcapply(springSecurity()) 设置为 outlined in the reference

      【讨论】:

      • 谢谢 Rob 之前的回答还可以,所以我会坚持下去,直到 4.1 发布。干杯。
      猜你喜欢
      • 1970-01-01
      • 2020-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-14
      • 2019-12-28
      • 1970-01-01
      • 2016-08-12
      相关资源
      最近更新 更多