java http 签名_java Http传输md5签名工具类

  • Post author:
  • Post category:java


从客户端转为服务端日记(一)

应用场景:

应用A请求应用B为保障数据不被非法篡改我们通常会对数据进行md5加密。

加密算法流程:

1.加入时间戳参数

2.根据字典树对请求的参数(Map)进行冒泡排序。

3.对数据进行格式化==> A=a&B=b&timestamp=121364565。

4.对格式化后的参数进行加密并加在格式化参数的末尾

验证算法流程

1.取出Map中的sigin

2.直接将map格式化并加密。比较md5是否一致

我将这个类用于拦截器中。当配置的请求非法时自动返回错误信息。

import java.io.UnsupportedEncodingException;

import java.net.URLEncoder;

import java.security.InvalidKeyException;

import java.security.NoSuchAlgorithmException;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;

import java.util.SortedMap;

import java.util.TreeMap;

import javax.crypto.Mac;

import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

public class SignedRequestHelperTest {

private static final String UTF8 = “UTF-8”;

private static final String HMAC_SHA256 = “HmacSHA256”;

private String secretKey = “myscretKey”;

private Mac mac;

private String urlParams;

public SignedRequestHelperTest(){

init();

}

private void init() {

try {

byte[] secretyKeyBytes = secretKey.getBytes(UTF8);

SecretKeySpec secretKeySpec = new SecretKeySpec(secretyKeyBytes, HMAC_SHA256);

mac = Mac.getInstance(HMAC_SHA256);

mac.init(secretKeySpec);

} catch (UnsupportedEncodingException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (NoSuchAlgorithmException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (InvalidKeyException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

/**

*

* @param params

* @return 没有urlecode的签名 params中sign是urlecode的签名

*/

public String sign(Map params) {

if (!params.containsKey(“timestamp”)) {

params.put(“timestamp”, timestamp());

}

SortedMap sortedParamMap = new TreeMap(params);

String canonicalQS = canonicalize(sortedParamMap);

String toSign = canonicalQS;

System.out.println(toSign);

String hmac = hmac(toSign);

String signed = percentEncodeRfc3986(hmac);

params.put(“sign”, signed);

sortedParamMap = new TreeMap(params);

this.setUrlParams(canonicalize(sortedParamMap));

return signed;

}

public boolean validSign(Map params) {

if (params.containsKey(“sign”)) {

String sign1 = params.get(“sign”);

params.remove(“sign”);

String sign2 = sign(params);

//System.out.println(sign1);

//System.out.println(sign2);

if (sign2.equals(sign1)) {

return true;

}

}

return false;

}

private String hmac(String stringToSign) {

String signature = null;

byte[] data;

byte[] rawHmac;

try {

data = stringToSign.getBytes(UTF8);

rawHmac = mac.doFinal(data);

Base64 encoder = new Base64();

signature = new String(encoder.encode(rawHmac));

} catch (UnsupportedEncodingException e) {

throw new RuntimeException(UTF8 + ” is unsupported!”, e);

}

return signature;

}

/**

* @return

*/

private String timestamp() {

return System.currentTimeMillis() + “”;

}

/**

* @param sortedParamMap

* @return

*/

private String canonicalize(SortedMap sortedParamMap) {

if (sortedParamMap.isEmpty()) {

return “”;

}

StringBuffer buffer = new StringBuffer();

Iterator> iter = sortedParamMap.entrySet().iterator();

while (iter.hasNext()) {

Map.Entry kvpair = iter.next();

buffer.append(percentEncodeRfc3986(kvpair.getKey()));

buffer.append(“=”);

buffer.append(percentEncodeRfc3986(kvpair.getValue()));

if (iter.hasNext()) {

buffer.append(“&”);

}

}

String canonical = buffer.toString();

return canonical;

}

/**

* Rfc3986

* 此处建议使用spring的encodeUri方法

* http://docs.spring.io/spring/docs/4.0.x/javadoc-api/org/springframework/

* web/util/UriUtils.html

*

* @param s

* @return

*/

private String percentEncodeRfc3986(String s) {

String out;

try {

out = URLEncoder.encode(s, UTF8).replace(“+”, “%20”).replace(“*”, “%2A”).replace(“%7E”, “~”);

} catch (UnsupportedEncodingException e) {

out = s;

}

return out;

}

public String getUrlParams() {

return urlParams;

}

public void setUrlParams(String urlParams) {

this.urlParams = urlParams;

}

public static void main(String[] args) throws Exception {

SignedRequestHelperTest signReqHelper = new SignedRequestHelperTest();

Map params = new HashMap();

params.put(“uname”, “username”);

params.put(“passwd”, “password”);

params.put(“a”, “a”);

System.out.println(signReqHelper.sign(params));

System.out.println(signReqHelper.validSign(params));

}

}

import java.io.IOException;

import java.io.PrintWriter;

import java.util.Enumeration;

import java.util.HashMap;

import java.util.Map;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import com.fh.controller.base.BaseController;

import com.fh.util.SignedRequestHelper;

public class MD5Filter extends BaseController implements Filter {

@Override

public void destroy() {

// TODO Auto-generated method stub

}

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)

throws IOException, ServletException {

logBefore(logger, “验证签名开始”);

HttpServletRequest request = (HttpServletRequest) req;

HttpServletResponse response = (HttpServletResponse) res;

Enumeration e = (Enumeration) request.getParameterNames();

Map map = new HashMap();

while (e.hasMoreElements()) {

String key = (String)e.nextElement();

map.put(key, request.getParameter(key));

}

try {

SignedRequestHelper sign = new SignedRequestHelper();

System.out.println(sign.validSign(map));

if(sign.validSign(map)){

chain.doFilter(req, res); // 调用下一过滤器

return;

}

} catch (Exception e2) {

// TODO: handle exception

logBefore(logger, “验证签名异常”);

}

response.setHeader(“Content-type”, “text/html;charset=UTF-8”);

response.setCharacterEncoding(“utf-8”);

PrintWriter out = response.getWriter();

String reString = “{\”errcode\”:10003,\”data\”:{},\”errmsg\”:\”签名错误\”}”;

out.write(reString);

}

@Override

public void init(FilterConfig arg0) throws ServletException {

// TODO Auto-generated method stub

}

}



版权声明:本文为weixin_30588381原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。