Prevenção de Submissão Duplicada com Spring MVC

Prevenção de Submissão Duplicada com Spring MVC

Em aplicações web, submissões repetidas de formulários podem causar prbolemas como inserções de dados múltiplas. Uma abordagem eficaz envolve o uso de tokens únicos associados à sessão do usuário, gerenicados por um enterceptor no Spring MVC para validar requisições e bloquear duplicatas.

Princípio Funcional

Um token aleatório, gerado por UUID, é armazenado na sessão do servidor. Ao processar uma requisição, o interceptor verifica se o token fornecido coincide com o da sessão. Se já foi utilizado, a requisição é rejeitada, evitando ação repetida.

Implementação via Código

1. Anotação Customizada

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DuplicatePrevention {

    boolean generateToken() default false;

    boolean checkToken() default false;
}

2. Interceptor de Validação

public class RequestValidationInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            DuplicatePrevention annotation = method.getAnnotation(DuplicatePrevention.class);
            if (annotation != null) {
                if (annotation.generateToken()) {
                    String uniqueToken = UUID.randomUUID().toString();
                    request.getSession().setAttribute("requestToken", uniqueToken);
                }
                if (annotation.checkToken()) {
                    if (hasDuplicateRequest(request)) {
                        return false; // Interrompe a execução
                    }
                    request.getSession().removeAttribute("requestToken");
                }
            }
        }
        return true;
    }

    private boolean hasDuplicateRequest(HttpServletRequest request) {
        String serverSideToken = (String) request.getSession().getAttribute("requestToken");
        if (serverSideToken == null) {
            return true;
        }
        String clientToken = request.getParameter("requestToken");
        if (clientToken == null || !serverSideToken.equals(clientToken)) {
            return true;
        }
        return false;
    }
}

3. Configuração no Spring MVC

<!-- Definição de interceptors -->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.project.RequestValidationInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

4. Aplicação em Controllers e Views

Para controladores que inicializam o token, utilize @DuplicatePrevention(generateToken=true). Naqueles que validam a submissão, adicione @DuplicatePrevention(checkToken=true).

No formulário HTML, insira um campo oculto para transmitir o token:

<input type="hidden" name="requestToken" value="${requestToken}" />

Tags: Spring MVC java interceptors Token Duplicate Submission Prevention

Publicado em 7-17 16:42