Spring Boot / Editorial solution guide

Separate HTTP validation and security rejections

Locate whether400,401,403,or404 came from routing, conversion, validation, authentication, authorization, or the selected disclosure policy.

About 3 min readContent reviewed

Read-only knowledge base ยท No public comments

Recognize the symptoms

A request may never reach the controller, while a direct method test succeeds. A state-changing call can return403 because of CSRF or authority, and malformed input may remain unseen until authentication is satisfied.

A generic public message is not enough to classify the boundary. Preserve safe request identity, method/path, content type, status, and restricted causal evidence.

Understand the likely causes

  • Selected filters, route mappings, conversion, Bean Validation, method security, advice, and entry/denial handlers can reject at different stages.
  • An incorrect media type, missing validation provider, unintended security chain, or wrong profile can change the observed path. Controller advice cannot handle every pre-MVC security failure.

Trace the request before changing policy

Record the exact application version, active security/configuration, method/path, request media type, intended identity/authority, and safe correlation id. Do not paste Authorization headers, cookies, passwords, or full private bodies into a public report. Determine whether routing matched and whether the controller/service was invoked. Distinguish intended error mapping from actual observed behavior rather than assuming a status code proves its cause.

Classify input and identity failures independently

400 can arise from conversion or validation under the selected contract;401 concerns authentication, while403 can mean denied authority or a CSRF check.404 can be route absence, missing data, or deliberate non-disclosure. Verify the configured handlers and cause. Do not disable CSRF, permit every path, or replace all failures with200 merely to reach a controller breakpoint.

Observe one conversion boundary under intended security

The fixture uses the earlier controller and security chain, supplies only the declared read authority, and requests a nonnumeric id. Its intended400 occurs at MVC conversion before ProductService is called. It requires Boot3.5 test/security dependencies and is not executed here. The synthetic principal does not verify real token/password handling, and a passing version would not prove POST/CSRF behavior.

java Illustrative conversion-before-service assertion
package training.catalog;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.context.annotation.Import;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.MockMvc;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WebMvcTest(ProductController.class)
@Import(ApiSecurity.class)
class BadProductIdFixture {
    @Autowired MockMvc mvc;
    @MockitoBean ProductService products;
    @Test @WithMockUser(authorities="catalog:read")
    void rejectsBeforeLookup() throws Exception {
        mvc.perform(get("/products/not-a-number"))
            .andExpect(status().isBadRequest());
        verifyNoInteractions(products);
    }
}

The configured controller path and authority are contextual. The test is proposed, not a performed request or observed Spring result.

Fix the evidenced contract, not the symptom

Correct the media type or parameter shape for conversion, register the intended validation provider and boundary for constraints, or repair the narrow identity/authority/CSRF configuration supported by the client model. Preserve object-level ownership checks even after route access succeeds. Keep public problem fields stable and safe, with raw causes in restricted diagnostics rather than exception or rejected-value dumps.

Verify the fix

Verify anonymous, missing-authority, authorized, cross-tenant, malformed, missing-resource, and relevant CSRF cases with the actual selected filters/advice. Assert both status/body and no forbidden service mutation. Separate mock identity policy tests from controlled credential-provider integration, and confirm diagnostic output remains redacted.

Keep it from recurring

  • Version request/error contracts and security rules together, keep denial regressions, and document supported browser/session/token flows. Never rely on CORS as authentication or on a successful direct method call as evidence of HTTP authorization and validation.

Official references