ConversionUtils.java
包含:
自增id转换方法
MD5+BASE64转换方法
import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; /** * @Author : JCccc * @CreateTime : 2019/12/6 * @Description : * 短链接生成 * 10进制,62进制互转 **/ @Slf4j public class ConversionUtils { /** * 初始化 62 进制数据,索引位置代表字符的数值,比如 A代表10,z代表61等 */ private static String chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; private static int scale = 62; /** * 将数字转为62进制 * * @param num Long 型数字 * @param length 转换后的字符串长度,不足则左侧补0 * @return 62进制字符串 */ public static String encode(long num, int length) { StringBuilder sb = new StringBuilder(); int remainder; // id混淆算法 long snum = num & 0xff000000; snum += (num & 0x0000ff00) << 8; snum += (num & 0x00ff0000) >> 8; snum += (num & 0x0000000f) << 4; snum += (num & 0x000000f0) >> 4; while (snum > scale - 1) { /* 对 scale 进行求余,然后将余数追加至 sb 中,由于是从末位开始追加的,因此最后需要反转(reverse)字符串 */ remainder = Long.valueOf(snum % scale).intValue(); sb.append(chars.charAt(remainder)); snum = snum / scale; } sb.append(chars.charAt(Long.valueOf(snum).intValue())); String value = sb.reverse().toString(); log.info("encode id: {}", snum); return StringUtils.leftPad(value, length, '0'); } /** * 62进制字符串转为数字 * * @param str 编码后的62进制字符串 * @return 解码后的 10 进制字符串 */ public static long decode(String str) { /* 将 0 开头的字符串进行替换 */ str = str.replace("^0*", ""); long num = 0; int index; for (int i = 0; i < str.length(); i++) { /* 查找字符的索引位置 */ index = chars.indexOf(str.charAt(i)); /* 索引位置代表字符的数值 */ num += (long) (index * (Math.pow(scale, str.length() - i - 1))); } // id混淆算法 long snum = num & 0xff000000; snum += (num & 0x00ff0000) >> 8; snum += (num & 0x0000ff00) << 8; snum += (num & 0x000000f0) >> 4; snum += (num & 0x0000000f) << 4; return snum; } public static String Md5CodeEncode(String longUrl, int urlLength) { if (urlLength < 4 ) { urlLength = 8;// defalut length } StringBuilder sbBuilder = new StringBuilder(urlLength + 2); String md5Hex = ""; int nLen = 0; while (nLen < urlLength) { // 这个方法是先 md5 再 base64编码 参见 // https://github.com/ndxt/centit-commons/blob/master/centit-utils/src/main/java/com/centit/support/security/Md5Encoder.java md5Hex = Md5Encoder.encodeBase64(md5Hex + longUrl); for(int i=0;i<md5Hex.length();i++){ char c = md5Hex.charAt(i); if(c != '/' && c != '+'){ sbBuilder.append(c); nLen ++; } if(nLen == urlLength){ break; } } } return sbBuilder.toString(); } public static void main(String[] args) { System.out.println("62进制:" + encode(1000000001L, 6)); System.out.println("10进制:" + decode("15t2ps")); System.out.println( Md5CodeEncode("http://abcd.cn/JCccc.html",6)); } }
Md5Encoder.java
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Hex; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * @Author : JCccc * @CreateTime : 2019/11/27 * @Description : **/ public abstract class Md5Encoder { private Md5Encoder() { throw new IllegalAccessError("Utility class"); } protected static final Logger logger = LoggerFactory.getLogger(Md5Encoder.class); public static byte[] rawEncode(byte[] data){ MessageDigest MD5; try { MD5 = MessageDigest.getInstance("MD5"); MD5.update(data, 0, data.length); return MD5.digest(); } catch (NoSuchAlgorithmException e) { logger.error(e.getMessage(),e);//e.printStackTrace(); return null; } } public static String encode(byte[] data){ byte [] md5Code = rawEncode(data); if(md5Code!=null){ return new String(Hex.encodeHex(md5Code)); } else { return null; } } public static String encode(String data){ try { return encode(data.getBytes("utf8")); } catch (UnsupportedEncodingException e) { logger.error(e.getMessage(),e);//e.printStackTrace(); return null; } } /** * 将md5 编码进行base64编码,去掉最后的两个==,16位的md5码base64后最后两位肯定是== * @param data 需要编码的 数据 * @param urlSafe 返回url合法字符 * @return 将md5 编码进行base64编码,去掉最后的两个== */ public static String encodeBase64(byte[] data, boolean urlSafe){ byte [] md5Code = rawEncode(data); if(md5Code != null){ return new String( urlSafe? Base64.encodeBase64URLSafe(md5Code): Base64.encodeBase64(md5Code),0,22); } else { return null; } } public static String encodeBase64(byte[] data){ return encodeBase64(data, false); } public static String encodeBase64(String data, boolean urlSafe){ try { return encodeBase64(data.getBytes("utf8"), urlSafe); } catch (UnsupportedEncodingException e) { logger.error(e.getMessage(),e);//e.printStackTrace(); return null; } } public static String encodeBase64(String data){ return encodeBase64(data, false); } /** * encoding password for spring security * 目前框架中的密码都是这样加密的 * @param data 密文 * @param salt 盐 * @return 散列值 */ public static String encodePasswordAsSpringSecurity(String data,String salt){ return encode(data + "{" + salt + "}"); } /** * encoding password for spring JA-SIG Cas * @param data 密文 * @param salt 盐 * @param iterations 迭代次数 * @return 散列值 */ public static String encodePasswordAsJasigCas(String data,String salt, int iterations){ MessageDigest MD5; try { MD5 = MessageDigest.getInstance("MD5"); byte[] saltBytes = salt.getBytes("utf8"); MD5.update(saltBytes, 0, saltBytes.length); byte[] hashedBytes = MD5.digest(data.getBytes("utf8")); for(int i=0;i<iterations-1;i++) hashedBytes = MD5.digest(hashedBytes); return new String(Hex.encodeHex(hashedBytes)); } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) { logger.error(e.getMessage(),e);//e.printStackTrace(); return null; } } /** * 先腾框架默认的密码算法 * @param data 密文 * @param salt 盐 * @return 散列值 */ public static String encodePassword(String data,String salt){ return encodePasswordAsSpringSecurity(data , salt); } /** * 先腾框架双重加密算法: 客户端 用md5将密码加密一下传输到后台,后台将密码再用salt加密一下放入数据库中 * 这个算法可以用于后台设置密码时使用,正常验证和以前一样。 * @param data 密文 * @param salt 盐 * @return 散列值 */ public static String encodePasswordWithDoubleMd5(String data,String salt){ return encodePasswordAsSpringSecurity( encode(data) , salt); } }