在 Spring MVC 单元测试中模拟匿名身份验证

Simulate Anonymous Authentication in Spring MVC Unit Test

我正在尝试为来宾用户帐户编写单元测试。被测代码通过调用此方法检查来宾,在单元测试中 returns 来宾帐户为 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 容器中,匿名用户可以 returns AnonymousAuthenticationToken 的一个实例。因为容器环境和单元测试环境共享相同的安全配置class,假设安全配置可能是正确的。

下面的测试代码也适用于 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();
}

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

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

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

在 Spring Security 4.1(尚未正式发布)中,我们引入了对 @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 做的一样,您需要确保使用 [=16] 设置 MockMvc =] 作为 outlined in the reference.