跟随上一篇的Gson序列化器方法的重写,涉及到了JWT的加密;

首先先简单介绍一下JWT:JWT是json web token缩写。它将用户信息加密到token里,服务器不保存任何用户信息。服务器通过使用保存的密钥验证token的正确性,只要正确即通过验证。

   优点是在分布式系统中,很好地解决了单点登录问题,很容易解决了session共享的问题。 
        缺点是无法作废已颁布的令牌/不易应对数据过期。

这里我们使用JWT对文件路径进行了加密,token失效时间为3分钟,接下来直接看代码吧:

  首先POM文件里面引入依赖

1        <dependency>
2             <groupId>com.auth0</groupId>
3             <artifactId>java-jwt</artifactId>
4             <version>3.3.0</version>
5         </dependency>

然后编辑自己的加密工具类:CommonEnctyptUtil.java

import com.alibaba.fastjson.JSONObject;
import com.apollo.alds.util.ConvertionUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.apache.log4j.Logger;

import java.io.UnsupportedEncodingException;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

/**
 * @Auther: SHIYIXIN
 * @Date: 2018/11/26 16:10
 * @Description: 文件名称加密工具类
 */
public class CommonEnctyptUtil {

    private static final Logger LOG = Logger.getLogger(CommonEnctyptUtil.class);


    private static  final String  KEY="DF94CBDCA294DC5DEF1368E64313FD3B98FE5EBCAB7F23AE";
    private static String getMessage(int code) {
        switch (code) {
            case 1:
                return "解密失败!";
            case 2:
                return "token为空无效";
            case 3:
                return "token无效或已过期";
            default:
                return "其他未知错误";
        }
    }

    /**
     *  文件加密
     * @param fileName 文件名
     * @param minutes  token 过期时间
     * @return 加密后文件名
     */
    public static String getAESResult(String fileName,int minutes){
        String result="";
        JSONObject json=new JSONObject();
        json.put("fileName",fileName);
        String token="";
        try {
             token=getToken(fileName,minutes);
            System.out.println("token="+token);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        if(!"".equals(token)){
            json.put("token",token);
        }
        result= AESUtil.encrypt(KEY, json.toJSONString());
        LOG.info("getAESResult="+result);
        return result;
    }

    /**
     *
     * @param fileName 文件名
     * @param minutes  过期时间
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String getToken( String fileName,int minutes) throws UnsupportedEncodingException {
        LOG.info("fileName:" + fileName);
        LOG.info("minutes:" + minutes);
        final Calendar instance = Calendar.getInstance();
        instance.add(Calendar.MINUTE, minutes);
        Algorithm algorithm = Algorithm.HMAC256("secret");
        String token = JWT.create().withClaim("fileName", fileName).withIssuer("auth0")
                .withExpiresAt(instance.getTime()).sign(algorithm);
        LOG.info("getToken="+token);

        return token;
    }

    /**
     *  密文解密
     * @param info 加密字符串
     * @return
     */
    public static Map getDecryptInfo(String info){
        Map result=new HashMap();
       boolean res=false;
       int code=0;
       String msg="";
        LOG.info("getDecryptInfo-----"+info);
        String  message=AESUtil.decrypt(KEY, info);//解密
        LOG.info("解密后信息:{}"+message);
        if(message!=null&&!"".equals(message)){
            JSONObject json=JSONObject.parseObject(message);
            String token= ConvertionUtil.getSimpleStringWithNull(json.get("token"));
            String fileName=ConvertionUtil.getSimpleStringWithNull(json.get("fileName"));

            if(!"".equals(token)){
                if(checktoken(fileName,token)){
                    res=true;
                    msg=fileName;
                }else{
                    code=3;
                    msg=getMessage(code);
                }
            }else{
                code=2;
                msg=getMessage(code);
            }
        }else{
            code=1;
            msg=getMessage(code);
        }
        result.put("result",res);
        result.put("code",code);
        result.put("msg",msg);
        LOG.info("getDecryptResult-----"+result);
        return result;
    }

    public static boolean checktoken(String fileName,String token) {
        LOG.info("fileName:" + fileName);
        boolean result=false;
        try {
                Algorithm algorithm = Algorithm.HMAC256("secret");
                JWTVerifier verifier = JWT.require(algorithm).withIssuer("auth0").withClaim("fileName", fileName).build(); // Reusable verifier instance
           // 这里需注意的是,依赖的fasterxml.jackson.core 的版本必须是2.9.2以上的
                DecodedJWT jwt = verifier.verify(token);
                result=true;
        } catch (JWTVerificationException ex) {
            // log
            LOG.info("authcheckfailed:", ex);
        } catch (UnsupportedEncodingException e) {
            LOG.info("编码错误:", e);
        } catch (Exception e){
            LOG.info("checktokenerror",e);
        }
        return result;
    }
}

AESUtil类:

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;

/**
 * @Auther: shiyixin
 * @Date: 2018/11/26 15:45
 * @Description:
 */
public class AESUtil {
    private static final Logger logger = Logger.getLogger(AESUtil.class);
    private static final String defaultCharset = "UTF-8";
    private static final String KEY_AES = "AES";
    private static final String KEY = "123456";
    /**
     * 加密
     *
     * @param data 需要加密的内容
     * @param key 加密密码
     * @return
     */
    public static String encrypt(String key,String data ) {
        return doAES(data, key, Cipher.ENCRYPT_MODE);
    }

    /**
     * 解密
     *
     * @param data 待解密内容
     * @param key 解密密钥
     * @return
     */
    public static String decrypt(String key,String data )  {
        return doAES(data, key, Cipher.DECRYPT_MODE);
    }

    /**
     * 加解密
     *
     * @param data 待处理数据
     * @param
     * @param mode 加解密mode
     * @return
     */
    private static String doAES(String data, String key, int mode) {
        try {
            if (StringUtils.isBlank(data) || StringUtils.isBlank(key)) {
                return null;
            }
            //判断是加密还是解密
            boolean encrypt = mode == Cipher.ENCRYPT_MODE;
            byte[] content;
            //true 加密内容 false 解密内容
            if (encrypt) {
                content = data.getBytes(defaultCharset);
            } else {
                content = parseHexStr2Byte(data);
            }
            //1.构造密钥生成器,指定为AES算法,不区分大小写
            KeyGenerator kgen = KeyGenerator.getInstance(KEY_AES);
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(key.getBytes());
            //2.根据ecnodeRules规则初始化密钥生成器
            //生成一个128位的随机源,根据传入的字节数组
            kgen.init(128, random);
            //3.产生原始对称密钥
            SecretKey secretKey = kgen.generateKey();
            //4.获得原始对称密钥的字节数组
            byte[] enCodeFormat = secretKey.getEncoded();
            //5.根据字节数组生成AES密钥
            SecretKeySpec keySpec = new SecretKeySpec(enCodeFormat, KEY_AES);
            //6.根据指定算法AES自成密码器
            Cipher cipher = Cipher.getInstance(KEY_AES);// 创建密码器
            //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY
            cipher.init(mode, keySpec);// 初始化
            byte[] result = cipher.doFinal(content);
            if (encrypt) {
                //将二进制转换成16进制
                return parseByte2HexStr(result);
            } else {
                return new String(result, defaultCharset);
            }
        } catch (Exception e) {
            
        }
        return null;
    }
    /**
     * 将二进制转换成16进制
     *
     * @param buf
     * @return
     */
    public static String parseByte2HexStr(byte buf[]) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }
    /**
     * 将16进制转换为二进制
     *
     * @param hexStr
     * @return
     */
    public static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1) {
            return null;
        }
        byte[] result =null;
        try {
            result= new byte[hexStr.length() / 2];
            for (int i = 0; i < hexStr.length() / 2; i++) {
                int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
                int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
                result[i] = (byte) (high * 16 + low);
            }
        }catch(Exception e){
            logger.info("parseHexStr2Byte密文处理异常");
        }
        return result;
    }
 
}

由于这个加密文件没有经过我手去写,我顺便加了注释进去,希望对大家能有帮助,可以得话记得添加一下关注,谢谢!

版权声明:本文为shixiaoxin-fighting原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/shixiaoxin-fighting/p/10024511.html