发布一个HTTP接口

1.签名验证的工具类:

  签名规则:

  1. 将所有请求参数转成JSON字符串。
  2. 将请求密钥分别添加到上述JSON字符串的头部和尾部,格式如下:

      secret请求参数JSON字符串secret

  3. 对该字符串进行MD5(签名)运算,得到一个二进制数组。

  4. 将该二进制数组转换为一个十六进制的字符串,该字符串是这些请求参数的签名。

  1 /**
  2  * 请求参数签名工具类
  3  *
  4  */
  5 public class ParamSignUtils {
  6 
  7     public static void main(String[] args) {
  8         HashMap<String, String> signMap = new HashMap<String, String>();
  9         String secret = "ywwXMYoWoS63u26fB1r4U";
 10         HashMap SignHashMap = ParamSignUtils.sign(signMap, secret);
 11         System.out.println("SignHashMap:" + SignHashMap);
 12         List<String> ignoreParamNames = new ArrayList<String>();
 13         ignoreParamNames.add("a");
 14         HashMap SignHashMap2 = ParamSignUtils.sign(signMap, ignoreParamNames, secret);
 15         System.out.println("SignHashMap2:" + SignHashMap2);
 16     }
 17 
 18     public static HashMap<String, String> sign(Map<String, String> paramValues, String secret) {
 19         return sign(paramValues, null, secret);
 20     }
 21 
 22     /**
 23      * @param paramValues
 24      * @param ignoreParamNames
 25      * @param secret
 26      * @return
 27      */
 28     public static HashMap<String, String> sign(Map<String, String> paramValues, List<String> ignoreParamNames,
 29             String secret) {
 30         try {
 31             HashMap<String, String> signMap = new HashMap<String, String>();
 32             StringBuilder sb = new StringBuilder();
 33             List<String> paramNames = new ArrayList<String>(paramValues.size());
 34             paramNames.addAll(paramValues.keySet());
 35             if (ignoreParamNames != null && ignoreParamNames.size() > 0) {
 36                 for (String ignoreParamName : ignoreParamNames) {
 37                     paramNames.remove(ignoreParamName);
 38                 }
 39             }
 40             Collections.sort(paramNames);
 41             sb.append(secret);
 42             for (String paramName : paramNames) {
 43                 sb.append(paramName).append(paramValues.get(paramName));
 44             }
 45             sb.append(secret);
 46             byte[] md5Digest = getMD5Digest(sb.toString());
 47             String sign = byte2hex(md5Digest);
 48             signMap.put("appParam", sb.toString());
 49             signMap.put("appSign", sign);
 50             return signMap;
 51         } catch (IOException e) {
 52             throw new RuntimeException("加密签名计算错误", e);
 53         }
 54 
 55     }
 56 
 57     /**
 58      * @param paramValues
 59      * @param ignoreParamNames
 60      * @param secret
 61      * @return
 62      */
 63     public static HashMap<String, String> sign(String paramValues, String secret) {
 64         try {
 65             HashMap<String, String> signMap = new HashMap<String, String>();
 66             StringBuilder sb = new StringBuilder(secret);
 67             if(!StringUtils.isBlank(paramValues)){
 68                 sb.append(paramValues);
 69             }
 70             sb.append(secret);
 71             byte[] md5Digest = getMD5Digest(sb.toString());
 72             String sign = byte2hex(md5Digest);
 73             signMap.put("appParam", sb.toString());
 74             signMap.put("appSign", sign);
 75             return signMap;
 76         } catch (IOException e) {
 77             throw new RuntimeException("加密签名计算错误", e);
 78         }
 79 
 80     }
 81 
 82     public static String utf8Encoding(String value, String sourceCharsetName) {
 83         try {
 84             return new String(value.getBytes(sourceCharsetName), "UTF-8");
 85         } catch (UnsupportedEncodingException e) {
 86             throw new IllegalArgumentException(e);
 87         }
 88     }
 89 
 90     private static byte[] getSHA1Digest(String data) throws IOException {
 91         byte[] bytes = null;
 92         try {
 93             MessageDigest md = MessageDigest.getInstance("SHA-1");
 94             bytes = md.digest(data.getBytes("UTF-8"));
 95         } catch (GeneralSecurityException gse) {
 96             throw new IOException(gse);
 97         }
 98         return bytes;
 99     }
100 
101     private static byte[] getMD5Digest(String data) throws IOException {
102         byte[] bytes = null;
103         try {
104             MessageDigest md = MessageDigest.getInstance("MD5");
105             bytes = md.digest(data.getBytes("UTF-8"));
106         } catch (GeneralSecurityException gse) {
107             throw new IOException(gse);
108         }
109         return bytes;
110     }
111 
112     private static String byte2hex(byte[] bytes) {
113         StringBuilder sign = new StringBuilder();
114         for (int i = 0; i < bytes.length; i++) {
115             String hex = Integer.toHexString(bytes[i] & 0xFF);
116             if (hex.length() == 1) {
117                 sign.append("0");
118             }
119             sign.append(hex.toUpperCase());
120         }
121         return sign.toString();
122     }
123 
124 }
View Code

2.获取HttpServletRequest的原生JSON参数

 1 //获取请求JSON字符串
 2     private String getParams(HttpServletRequest req) {
 3         String result = null;
 4         try {
 5             // 包装request的输入流
 6             BufferedReader br = new BufferedReader(
 7             new InputStreamReader((ServletInputStream) req.getInputStream(), "utf-8"));
 8             // 缓冲字符
 9             StringBuffer sb = new StringBuffer("");
10             String line;
11             while ((line = br.readLine()) != null) {
12                 sb.append(line);
13             }
14             br.close();// 关闭缓冲流
15             result = sb.toString();// 转换成字符
16             System.out.println("result = " + result);
17         } catch (Exception e) {
18             e.printStackTrace();
19         }
20         return result;
21     }
View Code

3.接口的具体实现

 1 @RequestMapping(value = "/getNoticeStockOutHeader", method = RequestMethod.POST)
 2     @ResponseBody
 3     public ResponseIntf getNoticeStockOutHeader(HttpServletRequest request, HttpServletResponse response) {
 4         response.setHeader("Access-Control-Allow-Origin", "*");// 跨域访问
 5         response.setCharacterEncoding("utf-8");
 6         ResponseIntf res = new ResponseIntf();
 7         try {
 8             request.setCharacterEncoding("utf-8");
 9             String json = this.getParams(request).replaceAll("\\s*", "");//去掉所有空格
10             String sign = request.getHeader("sign");
11             if(StringUtils.isBlank(sign)){
12                 throw new SecurityException("接口签名不能为空!");
13             }
14             if(!validateSign(json,sign)){
15                 throw new SecurityException("签名验证不通过!");
16             }
17             Gson gson = new Gson();
18             RequestIntf req = gson.fromJson(json, RequestIntf.class);
19             res.setResult(noticeStockOutService.getNoticeStockOutHeaderList(req));
20             res.setSuccess(true);
21             res.setMessage("调用成功");
22         } catch (IllegalArgumentException e) {
23             e.printStackTrace();
24             logger.error(StringUtils.getStackTrace(e));
25             res.setSuccess(false);
26             res.setMessage("参数不合法!错误信息:" + e.getMessage());
27         } catch (SecurityException e) {
28             e.printStackTrace();
29             logger.error(StringUtils.getStackTrace(e));
30             res.setSuccess(false);
31             res.setMessage("安全异常:" + e.getMessage());
32         } catch (AppException e) {
33             res.setSuccess(false);
34             res.setMessage(e.getMessage());
35         } catch (Exception e) {
36             e.printStackTrace();
37             logger.error(StringUtils.getStackTrace(e));
38             res.setSuccess(false);
39             res.setMessage("其它异常:" + e.getMessage());
40         }
41         return res;
42     }
View Code

4.接口采用MD5加密,直接获取原生的JSON字符串近行加密,与存放在request的header中的sign进行比对,相等,则验证成功。

posted @ 2017-09-15 15:51  vvning  阅读(3621)  评论(0编辑  收藏  举报