Java对方法参数进行签名加密

718 阅读2分钟

Java对方法参数进行签名加密

参数签名步骤

1.将请求参数中除 sign 外的多个键值对,按一定规则排序,拼成一个字符串

2.将 signKey 拼接在 第一步 中排序后的字符串前/后面得到待签名字符串

3.使用算法加密待加密字符串,得到sign

4.sign 添加到请求参数中

MD5加密算法

public final class MD5 {
    public static String encrypt(String strSrc) {
        try {
            char[] hexChars = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
                    '9', 'a', 'b', 'c', 'd', 'e', 'f'};
            byte[] bytes = strSrc.getBytes();
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(bytes);
            bytes = md.digest();
            int j = bytes.length;
            char[] chars = new char[j * 2];
            int k = 0;
            for (byte b : bytes) {
                chars[k++] = hexChars[b >>> 4 & 0xf];
                chars[k++] = hexChars[b & 0xf];
            }
            return new String(chars);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new RuntimeException("MD5加密出错: " + e);
        }
    }

    public static String encrypt2(String strSrc) {

        try {
            MessageDigest digest = MessageDigest.getInstance("md5");
            byte[] result = digest.digest(strSrc.getBytes());

            StringBuffer buffer = new StringBuffer();
            for (byte b : result) {
                int number = b & 0xff;
                String str = Integer.toHexString(number);
                if (str.length() == 1) {
                    buffer.append("0");
                }
                buffer.append(str);
            }
            return buffer.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new RuntimeException("MD5加密出错: " + e);
        }
    }
}

Signature签名工具类

@Slf4j
public class Signature {
    /**
     * 请求参数转Map
     *
     * @param paramMap
     * @return
     */
    public static Map<String, Object> switchMap(Map<String, String[]> paramMap) {
        Map<String, Object> resultMap = new HashMap<>();
        for (Map.Entry<String, String[]> param : paramMap.entrySet()) {
            resultMap.put(param.getKey(), param.getValue()[0]);
        }
        return resultMap;
    }

    /**
     * 请求数据获取签名
     *
     * @param paramMap 请求参数
     * @param signKey  签名Key
     * @return
     */
    public static String getSign(Map<String, Object> paramMap, String signKey) {
        paramMap.remove("sign");

        TreeMap<String, Object> sorted = new TreeMap<>(paramMap);
        StringBuilder str = new StringBuilder();
        for (Map.Entry<String, Object> param : sorted.entrySet()) {
            str.append(param.getValue()).append("|");
        }
        str.append(signKey);
        log.info("加密前:" + str.toString());
        String md5Str = MD5.encrypt(str.toString());
        log.info("加密后:" + md5Str);
        return md5Str;
    }

    /**
     * 签名校验
     *
     * @param paramMap 请求参数
     * @param signKey  签名Key
     * @return
     */
    public static boolean isSignEquals(Map<String, Object> paramMap, String signKey) {
        String sign = (String) paramMap.get("sign");
        String md5Str = getSign(paramMap, signKey);
        return sign.equals(md5Str);
    }

    /**
     * 获取时间戳
     *
     * @return
     */
    public static long getTimestamp() {
        return System.currentTimeMillis();
    }
}

代码示例

@RestController
public class TestController {

    private static final String SIGNKEY = "HelloWorld";

    /**
     * 使用加密算法加密字符串得到sign
     *
     * @return
     */
    @GetMapping("/getSign")
    public String getSign() {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("userName", "小白");
        paramMap.put("age", "20");
        return Signature.getSign(paramMap, SIGNKEY);
    }

    /**
     * 参数携带sign请求进行参数验证
     *
     * @param request
     * @return
     */
    @GetMapping("/verifySignature")
    public Object verifySignature(HttpServletRequest request) {
        // 参数转换成Map
        Map<String, Object> paramMap = Signature.switchMap(request.getParameterMap());

        // 进行参数签名验证
        if (!Signature.isSignEquals(paramMap, SIGNKEY)) {
            throw new RuntimeException("签名校验失败....");
        }
        return "success";
    }
}

执行测试

请求 http://localhost:8888/getSign生成Sign

c8dfaf36ad2a96d89e53c7e745d4db7f

请求http://localhost:8888/test?userName=小白&age=20&sign=c8dfaf36ad2a96d89e53c7e745d4db7f进行方法参数校验

success