判断sign签名(json格式)

7 篇文章 0 订阅

上一篇博文写的是sign签名,但是写的是form表单格式的数据,这篇写的是json格式

   /**
     * @param servletRequest
     * @param servletResponse
     * @return void
     * @Description: 验证sign签名
     * @Author Zangdy
     * @CreateTime 2019/4/22 12:57
     */
    private boolean verifySign(HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;

        //转换成代理类 从而解决以流的方式读取,但是读取完毕之后controller里的参数就为空的问题
        RequestWrapper requestWrapper = new RequestWrapper(httpServletRequest);
        ResponseWrapper wrapperResponse = new ResponseWrapper(httpServletResponse);
        // 签名
        String appKey = httpServletRequest.getParameter("appKey");
        String timeStamp = httpServletRequest.getParameter("timeStamp");
        String sign = httpServletRequest.getParameter("sign");
        // 判断参数是否为空
        if (StringUtils.isBlank(appKey) || StringUtils.isBlank(timeStamp) || StringUtils.isBlank(sign)) {
            return false;
        } else {
            StringBuilder signSb = new StringBuilder();
            // 以流的方式读取,但是读取完毕之后controller里的参数就为空了,所以需要用代理类去包装流来获取参数
            if ("POST".equalsIgnoreCase(httpServletRequest.getMethod())) {
                // 通过包装流获取参数, 并将字符串转成json对象
                JSONObject bodyJObject = JSONObject.parseObject(requestWrapper.getBody());
                for (String paraName : bodyJObject.keySet()) {
                    if (!"sign".equals(paraName)) {
                        signSb.append(paraName).append("=").append(bodyJObject.get(paraName)).append("&");
                    }
                }
            }
            // 获取拼接后的签名
            String signNew = signSb.substring(0, signSb.length() - 1);
            String[] signArr = signNew.split("&");
            // 将参数排序
            Arrays.sort(signArr);
            // 数组转字符串
            signNew = arrToString(signArr);
            signNew = signNew.replace("=", "");
            // 拼接securityKey(自己定义的私钥)
            signNew += securityKeyLocal;
            // 签名不合规
            if (!sign.equals(SecuritySHATool.shaEncrypt(signNew))) {
                return false;
            }
            // 获取当前时间毫秒值
            long time = System.currentTimeMillis();
            try {
                // 一次请求签名是否在有效时间内(时间自定义)
                if ((time - timeStampToDateTime(timeStamp)) > signTime) {
                    return false;
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return true;
    }
    
    /**
     * @param objects
     * @return java.lang.String
     * @Description: 数组转字符串
     * @Author Zangdy
     * @CreateTime 2019/4/22 10:18
     */
    public static String arrToString(Object[] objects) {
        StringBuilder sb = new StringBuilder();
        for (Object object : objects) {
            sb.append(object);
        }
        return sb.toString();
    }

    /**
     * @param timeStamp
     * @return java.lang.Long
     * @Description: 将时间戳转为毫秒值   yyyyMMddHHmmss
     * @Author Zangdy
     * @CreateTime 2019/4/22 11:42
     */
    public static Long timeStampToDateTime(String timeStamp) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        return sdf.parse(timeStamp).getTime();
    }
package com.sbkj.car.common;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Map;

/**
 * @Description: SHA 和 MD5工具类
 * @Author: 臧东运
 * @CreateTime: 2019/4/22 14:10
 */
public class SecuritySHATool {
    public static final String KEY_SHA = "SHA";
    public static final String KEY_MD5 = "MD5";


    /**
     * MD5加密字节
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encryptMD5(byte[] data) throws Exception {
        MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
        md5.update(data);
        return md5.digest();

    }

    /**
     * SHA加密字节
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encryptSHA(byte[] data) throws Exception {
        MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
        sha.update(data);
        return sha.digest();
    }


    /**
     * SHA加密
     *
     * @param inputStr
     * @return
     */
    public static String shaEncrypt(String inputStr) {
        byte[] inputData = inputStr.getBytes();
        String returnString = "";
        try {
            inputData = encryptSHA(inputData);
            for (int i = 0; i < inputData.length; i++) {
                returnString += byteToHexString(inputData[i]);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return returnString;
    }


    private static String byteToHexString(byte ib) {
        char[] digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a',
                'b', 'c', 'd', 'e', 'f'};
        char[] ob = new char[2];
        ob[0] = digit[(ib >>> 4) & 0X0F];
        ob[1] = digit[ib & 0X0F];

        String s = new String(ob);

        return s;
    }

    /**
     * MD5加密
     *
     * @param inputStr
     * @return
     */
    public static String md5Encrypt(String inputStr) {
        byte[] inputData = inputStr.getBytes();
        String returnString = "";
        try {
            BigInteger md5 = new BigInteger(encryptMD5(inputData));
            returnString = md5.toString(16);

        } catch (Exception e) {
            e.printStackTrace();
        }

        return returnString;
    }

    public static String dataDecrypt(Map<String, Object> serviceParams) {
        StringBuilder sb = new StringBuilder();
        Object[] keys = serviceParams.keySet().toArray();
        Arrays.sort(keys);
        for (Object key : keys) {
            sb.append(key).append(serviceParams.get(key));
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        System.out.println(shaEncrypt("username111password111"));
        System.out.println(md5Encrypt("111"));
    }
}

以下就是对应的包装类,可直接复制使用

package com.shuli.filter;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;

public class RequestWrapper extends HttpServletRequestWrapper {
    private final String body;

    public RequestWrapper(HttpServletRequest request) {
        super(request);
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader bufferedReader = null;
        InputStream inputStream = null;
        try {
            inputStream = request.getInputStream();
            if (inputStream != null) {
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                char[] charBuffer = new char[128];
                int bytesRead = -1;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
            } else {
                stringBuilder.append("");
            }
        } catch (IOException ex) {

        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        body = stringBuilder.toString();
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
        ServletInputStream servletInputStream = new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {
            }

            @Override
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }
        };
        return servletInputStream;

    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }

    public String getBody() {
        return this.body;
    }

}
package com.shuli.filter;


import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class ResponseWrapper extends HttpServletResponseWrapper {

    private ByteArrayOutputStream buffer;

    private ServletOutputStream out;

    public ResponseWrapper(HttpServletResponse httpServletResponse) {
        super(httpServletResponse);
        buffer = new ByteArrayOutputStream();
        out = new WrapperOutputStream(buffer);
    }

    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        return out;
    }

    @Override
    public void flushBuffer() throws IOException {
        if (out != null) {
            out.flush();
        }
    }

    public byte[] getContent() throws IOException {
        flushBuffer();
        return buffer.toByteArray();
    }

}

package com.shuli.filter;

import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class WrapperOutputStream extends ServletOutputStream {

    private ByteArrayOutputStream bos;

    public WrapperOutputStream(ByteArrayOutputStream bos) {
        this.bos = bos;
    }

    @Override
    public void write(int b) throws IOException {
        bos.write(b);
    }

    @Override
    public boolean isReady() {
        return false;
    }

    @Override
    public void setWriteListener(WriteListener arg0) {
      // 无
    }
}

细心的同志应该能发现我在最上面的注释中写了,只能读取一次,因为我的签名验证是在filter中做的,所以filter中读取完了之后controller就获取不到了。因此解决办法就是需要搞一个包装类,用来供我们去获取流。

如果发现什么问题请留言,毕竟代码都是人写的难免会出错。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 layui 的表格中添加点击事件,可以通过监听表格的 `tool` 事件来实现。具体步骤如下: 1. 在表格的 `toolbar` 中添加一个按钮,并设置一个自定义的 `lay-event` 值,用于区分不同的操作。 ```javascript toolbar: '<div class="layui-btn-container">' + '<button class="layui-btn layui-btn-sm" lay-event="add">添加</button>' + '</div>', ``` 2. 监听表格的 `tool` 事件,判断点击的按钮类型,并根据需要执行不同的操作。 ```javascript table.on('tool(test)', function(obj){ var data = obj.data; // 获取当前行数据 if(obj.event === 'add'){ // 判断点击的按钮类型 // 执行添加操作 console.log('add', data); } }); ``` 完整的代码示例如下: ```html <table id="test" lay-filter="test"></table> ``` ```javascript layui.use(['table'], function(){ var table = layui.table; // 渲染表格 table.render({ elem: '#test', url: '/demo/table/user/', toolbar: '<div class="layui-btn-container">' + '<button class="layui-btn layui-btn-sm" lay-event="add">添加</button>' + '</div>', cols: [[ {field:'id', title:'ID', width:80}, {field:'username', title:'用户名'}, {field:'email', title:'邮箱'}, {field:'sex', title:'性别', width:80}, {field:'city', title:'城市'}, {field:'sign', title:'签名'}, {field:'experience', title:'积分', width:80}, {field:'logins', title:'登入次数', width:100}, {field:'ip', title:'IP', width:120}, {field:'joinTime', title:'加入时间', width:120}, {fixed: 'right', title:'操作', toolbar: '<div><a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a><a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a></div>', width:120} ]] }); // 监听表格的 tool 事件 table.on('tool(test)', function(obj){ var data = obj.data; // 获取当前行数据 if(obj.event === 'add'){ // 判断点击的按钮类型 // 执行添加操作 console.log('add', data); } }); }); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值