使用自定义过滤器的MockMVC执行基本的Authentificaton点未调用DispatcherServlet

发布于 2025-01-29 20:02:25 字数 1554 浏览 2 评论 0原文

我使用@AutoconFigureMockmvc,所有无授权的请求和请求,都需要身份验证完美工作(使用调用dispatcherServlet),

但是当我尝试执行Auth Auth Point(用户名,密码)以进行全面测试认证时:

var resp = mockMvc.perform(post("/api/auth")
    .content(objectMapper.writeValueAsString(requestDto))
    .andExpect(status().isOk())
    .andReturn().getResponse().getContentAsString();

之后它被处理我的所有自定义身份验证过滤器,在身份验证上创建用户删除,但是变量reves是空的。

I try to debug (CustomUsernamePasswordAuthenticationFilter = CustomFilter):

CustomFilter.attemptAuthentication
CustomFilter.doFilter
CustomFilter.successfulAuthentication
this.successHandler.onAuthenticationSuccess
ForwardAuthenticationSuccessHandler.onAuthenticationSuccess
request.getRequestDispatcher(this.forwardUrl).forward(request, response)
MockRequestDispatcher.forward

MockRequestDispatcher.forward - this mock request dispatcher return empty response

When我通过Postman而不是MockRequestDisPatcher来调用/api/auth,它被称为applicationDisPatcher来自apache及其正向方法调用real dispatcherservlet < /code>

而不是自动配置的oigmvc,而是尝试使用它,无效:

mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
            .addFilters(filters)
            .build();

当我删除addfilters时,dispatcherServlet可以正常工作,但是身份验证未处理(过滤器不调用)

有人知道如何重写mockequequestDispatcherapplicationDispatcher mockmvc调用真实的dispatcherservlet和控制器?

I use @AutoConfigureMockMvc, all no-auth requests and requests, that needed authentication work perfectly (with calling DispatcherServlet)

But when I try to execute auth point (username, password) to fully test authentication:

var resp = mockMvc.perform(post("/api/auth")
    .content(objectMapper.writeValueAsString(requestDto))
    .andExpect(status().isOk())
    .andReturn().getResponse().getContentAsString();

After that it is processed all my custom authentication filters, create UserDetails in the auth context, but the variable resp is empty.

I try to debug (CustomUsernamePasswordAuthenticationFilter = CustomFilter):

CustomFilter.attemptAuthentication
CustomFilter.doFilter
CustomFilter.successfulAuthentication
this.successHandler.onAuthenticationSuccess
ForwardAuthenticationSuccessHandler.onAuthenticationSuccess
request.getRequestDispatcher(this.forwardUrl).forward(request, response)
MockRequestDispatcher.forward

MockRequestDispatcher.forward - this mock request dispatcher return empty response

When I call /api/auth via postman instead of MockRequestDispatcher, It is called ApplicationDispatcher from apache and Its forward method call real DispatcherServlet

Instead of auto configurable mockMvc, I tried to use this, no effect:

mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
            .addFilters(filters)
            .build();

When I remove addFilters, the DispatcherServlet works, but authentication not processed (filters don't calling)

Anybody knows the way how to rewrite the MockRequestDispatcher to the ApplicationDispatcher for MockMvc to call real DispatcherServlet and controller?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

━╋う一瞬間旳綻放 2025-02-05 20:02:25

我通过在Auth Filters中覆盖远期义务核心访问者来解决此问题:

@Bean
public MockMvc mockMvcWithAuthSupport(
        @Qualifier("springSecurityFilterChain") Filter springSecurityFilterChain,
        WebApplicationContext webApplicationContext
) {
    FilterChainProxy filterChain = (FilterChainProxy) springSecurityFilterChain;
    UsernamePasswordAuthenticationFilter[] filters = filterChain.getFilterChains().stream()
            .flatMap(chain -> chain.getFilters().stream())
            .filter(this::isUsernamePasswordFilter)
            .map(f -> (UsernamePasswordAuthenticationFilter) f)
            .peek(filter -> filter.setAuthenticationSuccessHandler(new MockMvcSuccessHandler()))
            .toArray(UsernamePasswordAuthenticationFilter[]::new);

    return MockMvcBuilders.webAppContextSetup(webApplicationContext)
            .addFilters(filters)
            .build();
}

自定义成功处理程序:

private class MockMvcSuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        MockFilterChain filterChain = new MockFilterChain(mockMvc.getDispatcherServlet(), new Filter[0]);
        filterChain.doFilter(request, response);
    }
}

I solved this by overriding the ForwardAuthenticationSuccessHandler in auth filters:

@Bean
public MockMvc mockMvcWithAuthSupport(
        @Qualifier("springSecurityFilterChain") Filter springSecurityFilterChain,
        WebApplicationContext webApplicationContext
) {
    FilterChainProxy filterChain = (FilterChainProxy) springSecurityFilterChain;
    UsernamePasswordAuthenticationFilter[] filters = filterChain.getFilterChains().stream()
            .flatMap(chain -> chain.getFilters().stream())
            .filter(this::isUsernamePasswordFilter)
            .map(f -> (UsernamePasswordAuthenticationFilter) f)
            .peek(filter -> filter.setAuthenticationSuccessHandler(new MockMvcSuccessHandler()))
            .toArray(UsernamePasswordAuthenticationFilter[]::new);

    return MockMvcBuilders.webAppContextSetup(webApplicationContext)
            .addFilters(filters)
            .build();
}

Custom success handler:

private class MockMvcSuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        MockFilterChain filterChain = new MockFilterChain(mockMvc.getDispatcherServlet(), new Filter[0]);
        filterChain.doFilter(request, response);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文