签名生成与验证

本文介绍了一种生成签名的方法,通过字母排序参数、MD5哈希和HMAC-SHA256加密,用于模拟HTTP请求的签名验证过程。重点展示了如何构造请求、计算MD5和签名,以及使用Spring框架进行测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

生成规则:

请求参数按照字母排序,key+value+requestBody的md5值,然后用app_secrete hmac256加密

生成代码:

@Test
    public void test() throws Exception {
        String appid="appid";
        long time=Instant.now().toEpochMilli();
        System.out.println("time is:"+time);
        String sign="";
        Map<String,String> phone=new HashMap<>();
//        phone.put("phone","11234");
        phone.put("phone","13100000000");
        MockHttpServletRequest request=new MockHttpServletRequest();
        request.setParameter("appid",appid);
        request.setParameter("t",String.valueOf(time));
        request.setParameter("sign",sign);
        request.setContentType("application/json");
        request.setContent(CommonUtils.toJson(phone).getBytes());
        Map<String,String[]> paramMap=request.getParameterMap();

        //获取md5值
        String bodyMd5=getMd5(request);
        //获取签名sign
        sign=getSign(paramMap,bodyMd5);
        //发送请求
        String url = "/test";
        MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get(url)
                .contentType(MediaType.APPLICATION_JSON)
                .param("appid",appid)
                .param("t",String.valueOf(time))
                .param("sign",sign)
                .content(CommonUtils.toJson(phone)))
                .andExpect(MockMvcResultMatchers.status().is(200))
                .andReturn();
        String res = result.getResponse().getContentAsString();
        System.out.println("res is:"+res);
    }

    private String getMd5(MockHttpServletRequest request){
        HttpServletRequest httpRequest=(HttpServletRequest)request;
        byte[] body = null;
        Map<String,String[]> map=request.getParameterMap();
        System.out.println("map is :"+CommonUtils.toJson(map));
        MultiReadRequestWrapper wrappedRequest = new MultiReadRequestWrapper(httpRequest);
        try (InputStream inputStream = wrappedRequest.getInputStream()) {
            final int size = inputStream.available();
            body = new byte[size];
            inputStream.read(body);
        } catch (Exception e) {
            System.out.println("Error reading the request body...");
        }
        String md5 = StringUtils.EMPTY;
        if (!Objects.isNull(body)) {
            try {
                md5 = outfox.edd.commoncredit.util.CommonUtils.getMd5Hex(body);
                System.out.println("body md5 is :"+ md5 + " body is :"+ new String(body));
            } catch (Exception e) {
                System.out.println("generate md5 error,"+e);
            }
        }
        return md5;
    }

    private String getSign(Map<String, String[]> params, String md5) throws InvalidKeyException, NoSuchAlgorithmException {
        final TreeMap<String, String> sequenceParams = new TreeMap<>();
        String sign = StringUtils.EMPTY;
        String appId = StringUtils.EMPTY;
        for (Map.Entry<String, String[]> stringEntry : params.entrySet()) {
            String k = stringEntry.getKey();
            String[] v = stringEntry.getValue();
            if (Constant.PARAM_SIGN.equals(k)) {
                sign = v[0];
                continue;
            }
            if (Constant.PARAM_APP_ID.equals(k)) {
                appId = v[0];
            }
            for (String s : v) {
                sequenceParams.put(k, s);
            }
        }

        StringBuilder input = new StringBuilder();
        sequenceParams.forEach((k, v) -> input.append(k).append(v));
        input.append(md5);
        String secrete = "secret";
        String signature= sign(input.toString().toLowerCase(), secrete);
        System.out.println("sign is "+signature);
        return signature;
    }


    /**
     * HmacSHA256加密
     * @param message 消息
     * @param secret  秘钥
     * @return 加密后字符串
     */
    public String sign(String message, String secret) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchAlgorithmException {
        Mac sha256hmac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
        sha256hmac.init(secret_key);
        byte[] bytes = sha256hmac.doFinal(message.getBytes());
        String hash = byteArrayToHexString(bytes);
        return hash;
    }

    /**
     * 将加密后的字节数组转换成字符串
     *
     * @param b 字节数组
     * @return 字符串
     */
    public String byteArrayToHexString(byte[] b) {
        StringBuilder hs = new StringBuilder();
        String stmp;
        for (int n = 0; b!=null && n < b.length; n++) {
            stmp = Integer.toHexString(b[n] & 0XFF);
            if (stmp.length() == 1) {
                hs.append('0');
            }
            hs.append(stmp);
        }
        return hs.toString().toLowerCase();
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值