java Sping Boot 2.5到2.6迁移后,当URL包含双斜杠时出现404错误

pbgvytdp  于 12个月前  发布在  Java
关注(0)|答案(4)|浏览(158)

以下URL用于在Sping Boot 2.5中返回200
http://localhost:8080//actuator/health
升级到2.6后,它不再工作,并返回404 Not Found
我发现了这个错误,因为项目的一些集成测试失败了(请求返回404)。然后我注意到了双斜杠,在删除它之后,问题得到了解决。
我只是想知道是什么特征导致了这种新行为?
我把2.6 release notes检查了几次,但没有任何印象。

lnvxswe2

lnvxswe21#

问题是路径匹配策略已更改。执行器路径模式不能被

spring.mvc.pathmatch.matching-strategy=ant-path-matcher

字符串
解决方案是手动修复包含双斜杠的URL。

dwbf0jvd

dwbf0jvd2#

1.您是否可以使用单斜杠访问执行器端点?如http://localhost:8080/actuator/health
1.如果是,那么你是否为你的应用程序配置了Spring Security ?你可以定义一个配置,你的应用程序将允许url中的连续斜杠。

@Bean
HttpFirewall httpFirewall() {
    StrictHttpFirewall firewall = new StrictHttpFirewall();
    firewall.setAllowUrlEncodedDoubleSlash(true);
    return firewall;
}

字符串

xpcnnkqh

xpcnnkqh3#

这可能是原因:基于PathPattern的Spring MVC路径匹配策略
根据注册的Spring MVC处理程序Map匹配请求路径的默认策略已从AntPathMatcher更改为PathPatternParser。
修复:

spring.mvc.pathmatch.matching-strategy=ant-path-matcher

字符串

agyaoht7

agyaoht74#

在 Spring Boot 3上测试:
1.创建RequestRejectedException处理程序:

@Component
public class CustomRequestRejectedHandler implements RequestRejectedHandler {

    @Override
    public void handle(HttpServletRequest req, HttpServletResponse res, RequestRejectedException ex) throws IOException {
        req.setAttribute("custom-error-id", ex.getMessage());
        res.sendError(HttpStatus.BAD_REQUEST.value());
    }
}

字符串
它将拦截RequestRejectedException,在这里您可以自定义http状态并添加一些用于异常识别的附加信息,这些信息将在接下来的步骤中使用。

  1. Spring将重定向已处理的错误到/error端点,这也是你需要实现的。创建如下内容:
@Controller
@RequestMapping("/error")
public class CustomErrorController implements ErrorController {

    @RequestMapping
    public ResponseEntity<ErrorResponse> handleError(HttpServletRequest request) {
        var httpStatus = resolveHttpStatus(request);
        var errorResponse = new ErrorResponse(extractErrorMessage(request, httpStatus));
        return new ResponseEntity<>(errorResponse, httpStatus);
    }

    protected HttpStatus resolveHttpStatus(HttpServletRequest request) {
        Integer statusCode = (Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
        if (statusCode == null) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }

        return Arrays.stream(HttpStatus.values())
                .filter(status -> status.value() == statusCode)
                .findFirst()
                .orElse(HttpStatus.INTERNAL_SERVER_ERROR);
    }

    private String extractErrorMessage(HttpServletRequest request, HttpStatus httpStatus) {
        var errorMessage = (String) request.getAttribute("custom-error-id");
        if (!Strings.isBlank(errorMessage)) {
            return errorMessage;
        } else {
            return httpStatus.getReasonPhrase();
        }
    }
}


1.最后将/error端点添加到spring WebSecurity配置排除列表中:

@EnableWebSecurity
@Configuration
public class SecurityConfig {
...
    @Bean
    public SecurityFilterChain web(HttpSecurity http) throws Exception {
        http
            ...
            .authorizeHttpRequests(auth-> auth
                .requestMatchers("/error").permitAll();
        ...
        return http.build();
    }


1.对于集成测试:使用WebTestClient实现它们。

相关问题