business.model.CaptchaModel.java Source code

Java tutorial

Introduction

Here is the source code for business.model.CaptchaModel.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package business.model;

import business.cache.BlackListCache;
import business.util.AESUtil;
import business.util.Util;
import captcha.thrift.CaptchaValidCode;
import captcha.thrift.ResultValidCaptcha;
import captcha.thrift.Token;
import com.jhlabs.image.RippleFilter;
import com.jhlabs.image.ShadowFilter;
import com.jhlabs.image.TransformFilter;
import com.vng.jcore.thriftutil.TSerializerBase;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.CubicCurve2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import service.log.LogObj;
import service.log.CaptchaScriber;
import tup_appinfo.AppInfoServiceClient;

/**
 *
 * @author dathn
 */
public class CaptchaModel {

    private static int width = 200;
    private static int height = 50;
    private static int numOfText = 6;
    private static Integer expireTime = 600;
    private static char[] chars = "36789WERTYUPDFHKXVBNM".toCharArray();
    public static int type = -1;
    public static Map<String, String> keyList = new HashMap<String, String>();
    private static final Logger log = LoggerFactory.getLogger(CaptchaModel.class);

    /**
     *
     * @param publicKey
     * @return
     */
    public static String GetPrivateKeyFromPublicKey(String publicKey) {
        try {
            String privateKey = keyList.get(publicKey);
            if (StringUtils.isBlank(privateKey)) {
                privateKey = AppInfoServiceClient.getInstance().getMainInfoByApiKey(publicKey).getSecretKey();
                if (StringUtils.isNotBlank(privateKey)) {
                    keyList.put(publicKey, privateKey);
                }
            }
            return privateKey;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return "";
    }

    /**
     *
     * @param tokenStr
     * @param privateKey
     * @return
     */
    public static Token decryptToken(String tokenStr, String privateKey) {
        Token token = new Token();
        try {
            byte[] tokenBytes = AESUtil.decrypt(tokenStr, privateKey);
            if (tokenBytes == null) {
                return null;
            }
            TSerializerBase.Deserialize(token, tokenBytes);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return token;

    }

    /**
     *
     * @return
     */
    public static String CreateCaptchaText() {
        try {
            return RandomStringUtils.random(CaptchaModel.numOfText, CaptchaModel.chars);
        } catch (Exception e) {
            log.warn(e.getMessage(), e);
        }
        return RandomStringUtils.randomAlphanumeric(CaptchaModel.numOfText);
    }

    /**
     *
     * @param logObj
     * @return
     */
    public static String GennarateToken(LogObj logObj) {
        try {
            long expireTime = Long.parseLong(CaptchaModel.expireTime.toString());
            Date currentDate = new Date();
            long currentTime = currentDate.getTime() / 1000L;
            expireTime = currentTime + expireTime;
            Token token = new Token();
            String tokenIp = RandomStringUtils.random(8, true, true);
            //            while (BlackListCache.getCache(tokenIp) != null) {
            //                tokenIp = RandomStringUtils.random(8, true, true);
            //            }
            token.setTokenIp(tokenIp);
            token.setCaptchaText(logObj.getCaptchaTrue());
            token.setExpireTime(expireTime);
            token.setIpAddress(Util.Ip2Int(logObj.getClientip()));
            String stringToken = AESUtil.encrypt(TSerializerBase.Serialize(token), logObj.getPrivatekey());
            logObj.setActionid(CaptchaScriber.GENTOKEN_SUCCESS);
            logObj.setToken(stringToken);
            CaptchaScriber.sendLog(logObj);
            return stringToken;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            logObj.setActionid(CaptchaScriber.GENTOKEN_FAIL);
            CaptchaScriber.sendLog(logObj);
        }
        return "";

    }

    /**
     *
     * @param CaptchaText
     * @return
     */
    public static BufferedImage CreateCaptchaImageOld(String CaptchaText) {
        BufferedImage localBufferedImage = new BufferedImage(width, height, 1);
        try {
            Graphics2D localGraphics2D = localBufferedImage.createGraphics();
            //        List<Font> fonts = FontFactory.getListFont();
            List<Font> fonts = new ArrayList<Font>();
            if (fonts.isEmpty()) {
                fonts.add(new Font("Nimbus Roman No9 L", 1, 30));
                fonts.add(new Font("VN-NTime", 1, 30));
                fonts.add(new Font("DT-Times", 1, 30));
                fonts.add(new Font("Times New Roman", 1, 30));
                fonts.add(new Font("Vni-Book123", 1, 30));
                fonts.add(new Font("VNI-Centur", 1, 30));
                fonts.add(new Font("DT-Brookly", 1, 30));
            }
            //        fonts.add(loadFont("BINHLBI.TTF"));
            RenderingHints localRenderingHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
            localRenderingHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            localGraphics2D.setRenderingHints(localRenderingHints);
            localGraphics2D.fillRect(0, 0, width, height);
            localGraphics2D.setColor(new Color(50, 50, 50));
            Random localRandom = new Random();
            int i = 0;
            int j = 0;
            for (int k = 0; k < CaptchaText.length(); k++) {
                i += 25 + Math.abs(localRandom.nextInt()) % 5;
                j = 25 + Math.abs(localRandom.nextInt()) % 20;
                int tmp = localRandom.nextInt(fonts.size() - 1);
                localGraphics2D.setFont(fonts.get(tmp));

                localGraphics2D.drawChars(CaptchaText.toCharArray(), k, 1, i, j);
            }
            localBufferedImage = getDistortedImage(localBufferedImage);
            Graphics2D localGraphics2D2 = localBufferedImage.createGraphics();
            localGraphics2D2.setRenderingHints(localRenderingHints);
            //        localGraphics2D2.fillRect(0, 0, width, height);
            localGraphics2D2.setColor(new Color(50, 50, 50));
            CubicCurve2D c = new CubicCurve2D.Double();// draw QuadCurve2D.Float with set coordinates
            for (int l = 0; l < 7; l++) {
                int x1 = Util.rand(0, width / 2);
                ;
                int x2 = Util.rand(width / 2, width);
                int y1 = Util.rand(0, height);
                int y2 = Util.rand(0, height);
                int ctrlx1 = (x1 + x2) / 4 * Util.rand(1, 3);
                int ctrly1 = y1;
                int ctrlx2 = (x1 + x2) / 4 * Util.rand(1, 3);
                int ctrly2 = y2;

                c.setCurve(x1, y1, ctrlx2, ctrly2, ctrlx1, ctrly1, x2, y2);
                localGraphics2D2.draw(c);
                //            localGraphics2D2.drawLine(randomX1(), randomY1(), randomX2(), randomY2());
            }

            localGraphics2D.dispose();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return null;
        }
        return localBufferedImage;
    }

    /**
     *
     * @param baseImage
     * @return
     */
    private static BufferedImage getDistortedImage(BufferedImage baseImage) {
        BufferedImage distortedImage = new BufferedImage(baseImage.getWidth(), baseImage.getHeight(),
                BufferedImage.TYPE_INT_ARGB);

        Graphics2D graph = (Graphics2D) distortedImage.getGraphics();

        ShadowFilter shadowFilter = new ShadowFilter();
        shadowFilter.setRadius(10);
        shadowFilter.setDistance(5);
        shadowFilter.setOpacity(1);

        Random rand = new Random();

        RippleFilter rippleFilter = new RippleFilter();
        rippleFilter.setWaveType(RippleFilter.SINE);
        rippleFilter.setXAmplitude(1.6f);
        rippleFilter.setYAmplitude(1.0f);
        rippleFilter.setXWavelength(5);
        rippleFilter.setYWavelength(2);
        rippleFilter.setEdgeAction(TransformFilter.BILINEAR);

        BufferedImage effectImage = rippleFilter.filter(baseImage, null);
        effectImage = shadowFilter.filter(effectImage, null);

        graph.drawImage(effectImage, 0, 0, null, null);
        graph.dispose();

        // draw lines over the image and/or text
        //      noiseProducer.makeNoise(distortedImage, .1f, .1f, .25f, .25f);
        return distortedImage;
    }

    /**
     *
     * @param token
     * @param privateKey
     * @return
     */
    public static String getCaptchaTextFromToken(String token, String privateKey) {
        Token decryptedToken = new Token();
        try {
            decryptedToken = CaptchaModel.decryptToken(token, privateKey);
            if (decryptedToken == null) {
                log.warn(
                        "getCaptchaTextFromToken : decrypt failed : token: " + token + " privateKey:" + privateKey);

                return "";
            }
            return decryptedToken.getCaptchaText();

        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return "";
    }

    /**
     *
     * @param tokenString
     * @param captchaText
     * @param privateKey
     * @param clientIp
     * @param logobj
     * @return
     */
    public static ResultValidCaptcha validateCaptcha(String tokenString, String captchaText, String privateKey,
            String clientIp, LogObj logobj) {
        ResultValidCaptcha rs = new ResultValidCaptcha();

        if (CaptchaModel.isInvalidRequest(tokenString, captchaText, privateKey)) {
            rs.setCode(CaptchaValidCode.INVALID_REQUEST);
            rs.setData(false);
            return rs;
        }
        if (CaptchaModel.isNotFoundPrivateKey(privateKey)) {
            rs.setCode(CaptchaValidCode.PRIVATEKEY_NOTFOUND);
            rs.setData(false);
            return rs;
        }
        Token decryptedToken;
        try {
            decryptedToken = CaptchaModel.decryptToken(tokenString, privateKey);
            logobj.setCaptchaTrue(decryptedToken.getCaptchaText());

            if (decryptedToken == null) {
                log.warn("validateCaptcha : decrypt failed : token: " + tokenString + " privateKey:" + privateKey
                        + "Logobj: " + logobj.toJson().toJSONString());
                throw new Exception();
            }
        } catch (Exception ex) {
            rs.setCode(CaptchaValidCode.DECRYPT_FAILED);
            rs.setData(false);
            return rs;
        }
        if (CaptchaModel.isTokenExpired(decryptedToken)) {
            rs.setCode(CaptchaValidCode.TOKEN_EXPIRED);
            rs.setData(false);
            return rs;
        }
        //        if (!CaptchaModel.isValidIp(decryptedToken, clientIp)) {
        //            resultValidCaptcha.setCode(CaptchaValidCode.IP_INVALID);
        //            resultValidCaptcha.setData(false);
        //            return resultValidCaptcha;
        //        }
        if (CaptchaModel.isTokenInBlackList(decryptedToken)) {
            rs.setCode(CaptchaValidCode.TOKEN_INBLACKLIST);
            rs.setData(false);
            return rs;
        }
        if (CaptchaModel.isCaptchaNotMatch(decryptedToken, captchaText)) {
            rs.setCode(CaptchaValidCode.CAPTCHA_NOTMATCH);
            rs.setData(false);
            return rs;
        }
        rs.setCode(CaptchaValidCode.VALID_SUCCESS);
        rs.setData(true);
        BlackListCache.standardize(decryptedToken.getTokenIp(), "true");
        return rs;
    }

    /**
     *
     * @param tokenString
     * @param captchaText
     * @param privateKey
     * @return
     */
    public static boolean isInvalidRequest(String tokenString, String captchaText, String privateKey) {
        return StringUtils.isBlank(tokenString) || StringUtils.isBlank(captchaText)
                || StringUtils.isBlank(privateKey);
    }

    /**
     *
     * @param token
     * @param clientIp
     * @return
     */
    public static boolean isValidIp(Token token, String clientIp) {
        int ipInt = Util.Ip2Int(clientIp);
        return ipInt == token.getIpAddress();

    }

    /**
     *
     * @param token
     * @return
     */
    public static boolean isTokenExpired(Token token) {
        long currentTime = System.currentTimeMillis() / 1000L;
        return token.getExpireTime() < currentTime;
    }

    /**
     *
     * @param token
     * @return
     */
    public static boolean isTokenInBlackList(Token token) {
        String isInBlackList = BlackListCache.getCache(token.getTokenIp());
        return isInBlackList != null;
    }

    /**
     *
     * @param token
     * @param captchaText
     * @return
     */
    public static boolean isCaptchaNotMatch(Token token, String captchaText) {
        return !captchaText.toUpperCase().equals(token.getCaptchaText());
    }

    /**
     *
     * @param privateKey
     * @return
     */
    public static boolean isNotFoundPrivateKey(String privateKey) {
        //        
        //        if (!CaptchaModel.KeyList.containsValue(privateKey)) {
        //            return true;
        //        }

        return false;
    }

}