Prevent Duplicate Submissions with JWT Tokens in a Java Backend

This article explains how to use JWT tokens in a Java backend to prevent duplicate form submissions, covering the problem of repeated clicks, two mitigation approaches, detailed token generation utilities, session handling methods, and practical code examples for creating, validating, and managing tokens.

Senior Brother's Insights
Senior Brother's Insights
Senior Brother's Insights
Prevent Duplicate Submissions with JWT Tokens in a Java Backend

Purpose

The goal is to generate a token in a Java e‑commerce backend to validate client requests and prevent duplicate submissions caused by users repeatedly clicking a submit button.

Overview

In web projects the client and server exchange data frequently. When network latency is high, a user may click the submit button multiple times, causing the same sensitive data to be stored more than once. This needs to be avoided.

Solution

Frontend: hide or disable the submit button immediately after the first click using JavaScript.

Backend: verify each request by comparing a unique token sent from the client with a token stored on the server (session).

The backend approach is more reliable because it enforces validation regardless of client‑side behavior.

Core Code

Token generation utility (TokenProccessor):

/**
 * 生成Token的工具类
 */
package red.hearing.eval.modules.token;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
import sun.misc.BASE64Encoder;

public class TokenProccessor {
    private TokenProccessor() {}
    private static final TokenProccessor instance = new TokenProccessor();
    public static TokenProccessor getInstance() { return instance; }
    /** 生成Token */
    public String makeToken() {
        String token = System.currentTimeMillis() + new Random().nextInt(999999999) + "";
        try {
            MessageDigest md = MessageDigest.getInstance("md5");
            byte[] md5 = md.digest(token.getBytes());
            BASE64Encoder encoder = new BASE64Encoder();
            return encoder.encode(md5);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }
}

Token handling utilities (TokenTools):

package red.hearing.eval.modules.token;

import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;

public class TokenTools {
    /** 将生成的token放入session */
    public static void createToken(HttpServletRequest request, String tokenServerkey) {
        String token = TokenProccessor.getInstance().makeToken();
        request.getSession().setAttribute(tokenServerkey, token);
    }
    /** 移除session中的token */
    public static void removeToken(HttpServletRequest request, String tokenServerkey) {
        request.getSession().removeAttribute(tokenServerkey);
    }
    /** 判断请求参数中的token是否与session中的一致 */
    public static boolean judgeTokenIsEqual(HttpServletRequest request, String tokenClientkey, String tokenServerkey) {
        String token_client = request.getParameter(tokenClientkey);
        if (StringUtils.isEmpty(token_client)) return false;
        String token_server = (String) request.getSession().getAttribute(tokenServerkey);
        if (StringUtils.isEmpty(token_server)) return false;
        if (!token_server.equals(token_client)) return false;
        return true;
    }
}

Usage steps:

Before rendering a page, call TokenTools.createToken(request, "myTokenKey") to store a token in the session.

When the user submits the form, read the token from the session and include it in the request parameters.

On the server side, invoke

TokenTools.judgeTokenIsEqual(request, "myTokenKey", "myTokenKey")

; if it returns false, reject the request.

Note: tokenClientkey and tokenServerkey are custom names; the key used in judgeTokenIsEqual must match the one sent from the frontend.

Extended Example – OAuth Token Manager

A more complete JWT handling class is shown below, illustrating how to create, sign, and validate tokens using the JJWT library.

import io.jsonwebtoken.*;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;

public class OAuthTokenManager {
    private String APP_ID = "";
    private String APP_SECRET = "";
    private String KEY_SING = ""; // placeholder for Redis key
    public static final int MINUTE_TTL = 60 * 1000;
    // ... other TTL constants omitted for brevity
    private OAuthTokenManager() {}
    private static OAuthTokenManager single = null;
    public static OAuthTokenManager getInstance() {
        if (single == null) single = new OAuthTokenManager();
        return single;
    }
    private SecretKey generalKey() {
        String stringKey = APP_ID + APP_SECRET;
        byte[] encodedKey = Base64.decodeBase64(stringKey);
        return new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
    }
    public String createToken(String subject, long ttlMillis) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        SecretKey key = generalKey();
        JwtBuilder builder = Jwts.builder()
                .setId(APP_ID)
                .setIssuedAt(now)
                .setSubject(subject)
                .signWith(signatureAlgorithm, key);
        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;
            builder.setExpiration(new Date(expMillis));
        }
        return builder.compact();
    }
    public Claims validateToken(String token) throws Exception {
        return Jwts.parser()
                .setSigningKey(generalKey())
                .parseClaimsJws(token)
                .getBody();
    }
}

Dependency for JJWT (add to Maven pom):

<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt</artifactId>
  <version>0.7.0</version>
</dependency>

These snippets together provide a practical way to generate unique tokens, store them in the user's session, and verify them on each request, effectively preventing duplicate submissions and adding a lightweight security layer to Java web applications.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendJavaSecurityJWTToken
Senior Brother's Insights
Written by

Senior Brother's Insights

A public account focused on workplace, career growth, team management, and self-improvement. The author is the writer of books including 'SpringBoot Technology Insider' and 'Drools 8 Rule Engine: Core Technology and Practice'.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.