Spring Boot simplifie les endpoints webhook avec @RestController, mais Spring Security CSRF et les convertisseurs JSON peuvent bloquer ou modifier le payload avant votre handler. Le test local doit prouver l'accès byte[] brut, l'exemption CSRF sur les chemins webhook et la vérification de signature sur octets intacts.
Créer un endpoint webhook @RestController
Gardez les contrôleurs webhook légers. Acceptez les bytes bruts, vérifiez la signature, puis désérialisez :
@RestController
@RequestMapping("/webhooks")
public class StripeWebhookController {
@PostMapping("/stripe")
public ResponseEntity handle(
@RequestBody byte[] payload,
@RequestHeader("Stripe-Signature") String signature) {
if (!verifier.isValid(payload, signature)) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
JsonNode event = objectMapper.readTree(payload);
handler.process(event);
return ResponseEntity.ok().build();
}
}
@RequestBody byte[] préserve le payload exact reçu par Tomcat — idéal quand le provider signe du JSON brut.
Lire le corps brut via HttpServletRequest
Alternativement, lisez directement depuis la requête servlet :
byte[] body = request.getInputStream().readAllBytes();
String sig = request.getHeader("Stripe-Signature");
Évitez de lier à un POJO ou Map d'abord — la resérialisation Jackson casse les HMAC. Voir le guide de vérification de signature.
Désactiver CSRF uniquement pour les webhooks
Spring Security active CSRF par défaut. Les POST webhook échouent en 403 sans exemption server-to-server :
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(csrf -> csrf.ignoringRequestMatchers("/webhooks/**"));
return http.build();
}
}
Limitez l'ignore à /webhooks/** — ne désactivez pas CSRF globalement.
Vérifier les en-têtes de signature avant la logique métier
Lisez les en-têtes provider, calculez le digest depuis le tableau d'octets brut et comparez en temps constant. 401 si échec, 200 rapide pour limiter les retries.
Workflow tunnel local
- Démarrez :
./mvnw spring-boot:runsur le port 8080. - Exposez Tomcat :
npx portpreview 8080. - Collez l'URL tunnel + chemin dans le dashboard provider.
- Envoyez un événement test et surveillez les logs.
- Rejouez le même event ID pour confirmer l'idempotence — voir patterns retry.
Pièges courants
Ordre des filtres et consommation du body
Les filtres qui lisent le stream avant le contrôleur le vident. Utilisez ContentCachingRequestWrapper si plusieurs couches inspectent le body.
Binding @RequestBody global
Un @ControllerAdvice qui parse le JSON tôt peut altérer les octets. Isolez les endpoints webhook avec binding byte[].
Handlers lents déclenchent des retries
Accusez réception vite, traitez en async, dédupliquez par event ID.
Pour aller plus loin
Pour les bases, lisez les bases du tunneling localhost et le débogage webhook en local. Pour la cryptographie, consultez le guide de vérification de signature. Pour les handlers sans doublons, voyez les patterns retry et idempotence. commencez PortPreview gratuitement.
![Un RestController Spring Boot sur Tomcat embarqué vérifiant les en-têtes de signature webhook depuis un payload byte[] brut reçu via un tunnel local.](/_next/image?url=%2Fimages%2Farticles%2Fspring-boot-webhook-local-testing%2Fcover.png&w=3840&q=75)