Backend Development 16 min read

Java Backend Token Generation Using JWT: Implementation and Usage Guide

This article explains how to prevent duplicate form submissions in Java web applications by generating and validating JWT tokens on the backend, provides complete utility classes and controller examples, and includes step‑by‑step usage instructions with full source code.

Top Architect
Top Architect
Top Architect
Java Backend Token Generation Using JWT: Implementation and Usage Guide

The purpose of the article is to demonstrate how to generate a token in a Java backend for validating client requests and preventing duplicate submissions, using an open‑source JWT architecture.

Overview

In web projects, the client may click the submit button multiple times, causing duplicate data; a token can be used to ensure each request is processed only once.

Solution

1. Front‑end: hide or disable the submit button after clicking. 2. Back‑end: generate a unique token, store it in the session, and validate the token on each request.

Conclusion

The back‑end token validation method is more secure and solves the problem fundamentally, so it is the recommended approach.

Core Code

Token generation utility class:

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

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

import sun.misc.BASE64Encoder;

/**
 * 生成Token的工具类
 * @author zhous
 * @since 2018-2-23 13:59:27
 */
public class TokenProccessor {
    private TokenProccessor(){};
    private static final TokenProccessor instance = new TokenProccessor();
    public static TokenProccessor getInstance(){
        return instance;
    }
    /**
     * 生成Token
     * @return
     */
    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 utility class for session handling:

/**
 * Token的工具类
 */
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);
    }
    /**
     * 移除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;
    }
}

OAuth token manager (JWT creation and validation):

package com.franz.websocket;

import com.franz.common.utils.StringUtils;
import com.franz.weixin.p3.oauth2.util.MD5Util;
import io.jsonwebtoken.*;
import net.sf.json.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.jeecgframework.core.common.service.CommonService;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.DatatypeConverter;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * OAuthTokenUtils
 * Token管理
 */
public class OAuthTokenManager {
    private String APP_ID = "";
    private String APP_SECRET = "";
    private String KEY_SING = ""; // 用于存放TOKEN的标志,Redis
    private LinkedHashMap
pairs = new LinkedHashMap(); // 封装json的map
    private CommonService service;
    public static final int MINUTE_TTL = 60*1000; // millisecond
    public static final int HOURS_TTL = 60*60*1000; // millisecond
    public static final int DAY_TTL = 12*60*60*1000; // millisecond

    private OAuthTokenManager() {}
    private static OAuthTokenManager single=null;
    public static OAuthTokenManager getInstance(){
        if (single == null) {
            single = new OAuthTokenManager();
        }
        return single;
    }
    public String getKEY_SING(){
        return KEY_SING;
    }
    public void setPairs(LinkedHashMap
pairs){
        this.pairs = pairs;
    }
    public LinkedHashMap
getPairs(){
        return pairs;
    }
    public void put(String key, Object value){
        pairs.put(key, value);
    }
    public void remove(String key){
        pairs.remove(key);
    }
    /**
     * 总体封装
     */
    public String token(String appid,String secret,LogicInterface logicInterface){
        this.accessPairs(appid,secret);
        Object subject = this.loginAuthentication(logicInterface);
        String token = this.createToken(this.generalSubject(subject),this.MINUTE_TTL);
        return token;
    }
    public void accessPairs(String APP_ID, String APP_SECRET) {
        this.APP_ID = APP_ID;
        this.APP_SECRET = APP_SECRET;
        // this.KEY_SING = MD5Util.MD5Encode(APP_ID+"_"+APP_SECRET,"UTF-8").toUpperCase();
    }
    public Object loginAuthentication(LogicInterface logicInterface){
        if(StringUtils.isNotBlank(APP_ID) && StringUtils.isNotBlank(APP_SECRET)) {
            Map
map = new HashMap<>();
            map.put("APP_ID",APP_ID);
            map.put("APP_SECRET",APP_SECRET);
            if(logicInterface == null || logicInterface.handler(map) == null){
                return map;
            } else {
                return logicInterface.handler(map);
            }
        } else {
            return null;
        }
    }
    public SecretKey generalKey(){
        String stringKey = APP_ID+APP_SECRET;
        byte[] encodedKey = Base64.decodeBase64(stringKey);
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }
    public static String generalSubject(Object obj){
        if(obj != null ) {
            JSONObject json = JSONObject.fromObject(obj);
            return json.toString();
        } else {
            return "{}";
        }
    }
    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;
            Date exp = new Date(expMillis);
            builder.setExpiration(exp);
        }
        return builder.compact();
    }
    public Claims validateToken(String token) throws Exception{
        Claims claims = Jwts.parser()
                .setSigningKey(generalKey())
                .parseClaimsJws(token).getBody();
        return claims;
    }
}

Controller that exposes token creation and validation endpoints:

package com.franz.websocket;

import com.franz.common.utils.StringUtils;
import com.franz.weixin.p3.oauth2.util.MD5Util;
import io.jsonwebtoken.*;
import net.sf.json.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.jeecgframework.core.common.service.CommonService;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * OAuthTokenController
 */
@Scope("prototype")
@Controller
@RequestMapping("/oAuthToken")
public class OAuthToken {
    @RequestMapping(params = "token", method = RequestMethod.GET)
    @ResponseBody
    public Object token(@RequestParam(value = "grant_type") String grant_type,
                        @RequestParam(value = "appid") String appid,
                        @RequestParam(value = "secret") String secret,
                        HttpServletResponse response) {
        Map
map = new HashMap<>();
        switch (grant_type) {
            case "client_credentials":
                OAuthTokenManager oAuthTokenManager = OAuthTokenManager.getInstance();
                String token = oAuthTokenManager.token(appid, secret, null);
                map.put("access_token", token);
                map.put("expires_in", OAuthTokenManager.MINUTE_TTL/1000);
                break;
            // other cases omitted for brevity
        }
        return map;
    }
    // loginAuth2 and index methods omitted for brevity
}

Maven dependency for JJWT library:

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

Usage Steps

Call TokenTools.createToken(request, "TOKEN_KEY") before rendering the page to store a token in the session.

When the front‑end submits data, include the token from the session.

On the server, invoke TokenTools.judgeTokenIsEqual(request, "clientTokenKey", "TOKEN_KEY") to verify the token; reject the request if validation fails.

Note: tokenClientkey and tokenServerkey are custom names and must match between front‑end and back‑end.

The token acts as a one‑time credential that prevents duplicate submissions and protects sensitive operations.

backendJavawebSpringsecurityJWTtoken
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login 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.