开发者社区 问答 正文

在HttpSecurityConfig上使用访问控制时,WithMockUser不起作用

如果使用hasAuthority或hasRole功能,则可以@WithMockUser在测试中使用。但是,如果我使用access该方法,则无法@WithMockUser与正确的用户对象一起使用。

@Bean
public HttpSecurityConfig securityConfiguration() {
    return http -> {
        http.authorizeExchange()
            .pathMatchers(HttpMethod.GET, "/api/**")
            .access(<ReactiveAuthorizationManager>));
    };
}

如何为受上述保护的控制器编写测试HttpSecurityConfig?我需要创建一个UserDetail用于交换的伪对象(我认为)。我使用Webflux。

展开
收起
垚tutu 2019-12-19 16:29:36 726 分享 版权
阿里云 AI 助理回答

在使用Spring Security测试Webflux应用时,特别是当你需要模拟具有特定权限的用户来测试access()方法时,可以采用以下步骤编写测试。这里的关键是利用MockServerHttpRequestWebTestClient来构建请求上下文,并手动设置SecurityContext。

首先,确保你有相应的依赖,比如Spring Boot Starter Test包含WebFlux测试支持:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
    </exclusions>
</dependency>

然后,在你的测试类中,你可以创建一个WebTestClient实例并配置它以适应你的安全需求。对于access()方法,你可能需要直接构造一个具有期望角色或权限的UserDetails对象,并将其放入到SecurityContext中。下面是一个示例:

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers;
import org.springframework.test.web.reactive.server.WebTestClient;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class YourControllerTest {

    @Autowired
    private WebTestClient webTestClient;

    @BeforeEach
    public void setup() {
        // 配置WebTestClient以模拟具有特定权限的用户
        UserDetails userDetails = User.withUsername("test")
                                       .password("") // 密码通常不重要,因为不会进行验证
                                       .authorities(new SimpleGrantedAuthority("ROLE_ADMIN"))
                                       .build();
        
        webTestClient = webTestClient.mutate()
                                     .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                                     .configureClient()
                                     .filter((request, next) -> {
                                         request.headers().header(HttpHeaders.AUTHORIZATION, "Bearer mockToken"); // 如果需要的话,可以添加JWT令牌等
                                         return next.exchange(request);
                                     })
                                     .build();
    }

    @Test
    public void testProtectedEndpoint() {
        webTestClient.get().uri("/api/someProtectedEndpoint")
                     .attributes(SecurityMockServerConfigurers.mockAuthentication(userDetails)) // 设置SecurityContext
                     .exchange()
                     .expectStatus().isOk() // 或者其他预期的状态码
                     .expectBody(String.class).isEqualTo("Expected response");
    }
}

请注意,上述代码中的userDetails需要根据你的实际需求来构建,包括用户名、密码(尽管在测试中可能并不重要)以及相关的权限或角色。通过SecurityMockServerConfigurers.mockAuthentication(userDetails),我们能够将这个用户详细信息注入到测试的HTTP请求的安全上下文中,从而模拟出拥有特定权限的用户访问受保护端点的情况。

如果你的应用使用了JWT或其他形式的令牌认证,你可能还需要适当配置如何处理这些令牌,以便正确地模拟认证过程。

有帮助
无帮助
AI 助理回答生成答案可能存在不准确,仅供参考
0 条回答
写回答
取消 提交回答