客户端
Client.java
/**
* 向服务器发送请求并解析返回响应结果
* @param url - 请求的地址
* @param baseClientDTO - 请求的参数
* @param type - 返回参数的类型
* @return 返回参数实例
* @throws IOException
*/
public static T sendAndReturn(String url, BaseClientDTO baseClientDTO, TypeReference type) throws IOException {
//TODO 基于hmac256(baseClientDTO,secretKey)签名,服务器同样签名后比对,相同为真,不同为否
String param = JSON.toJSONString(baseClientDTO);
URL realUrl = new URL(url);
// 打开和URL之间的连接
HttpURLConnection connection = (HttpURLConnection)realUrl.openConnection();
// 设置通用的请求属性
connection.setConnectTimeout(10000);
connection.setReadTimeout(20000);
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("POST");
connection.setUseCaches(false);
connection.setInstanceFollowRedirects(true);
connection.setRequestProperty("Content-Type","application/json;charset=utf-8");
//签名设置
String secretKey = OccDownloadService.getInstance().secretKey;
String signature = null;
if (secretKey != null) {
signature = SecretUtil.hmac256(param,secretKey);
}
connection.setRequestProperty("signature", signature);
connection.setRequestProperty("envCode", baseClientDTO.getEnvCode());
connection.setRequestProperty("nsCode", baseClientDTO.getNsCode());
connection.setRequestProperty("clientLocalIp",_CLIENT_LOCAL_IP);
connection.connect();
PrintWriter out = null;
BufferedReader br = null;
InputStreamReader ir = null;
try {
// 获取URLConnection对象对应的输出流
out = new PrintWriter(connection.getOutputStream());
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
//是否请求成功
InputStream inputStream = (connection.getResponseCode() == HttpURLConnection.HTTP_OK) ?
connection.getInputStream() :
connection.getErrorStream();
//获取数据
br = new BufferedReader(ir = new InputStreamReader(inputStream,"UTF-8"));
String line;
StringBuilder result = new StringBuilder();
while ((line = br.readLine()) != null) {
result.append(line);
}
return JSON.parseObject(result.toString(), type);
}finally {
close(out,br,ir);
connection.disconnect();
}
}
SecretUtil.java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
/**
* Created by Think on 2017/3/20.
*/
public class SecretUtil {
/**
* 签名加密
*
* @param str
* @param stal
* @return
*/
public static String hmac256(String str, String stal) {
Mac hmac;
try {
hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec macKey = new SecretKeySpec(stal.getBytes(), "RAW");
hmac.init(macKey);
byte[] key = hmac.doFinal(str.getBytes());
return byteToHexString(key);
} catch (Exception e) {
return null;
}
}
/**
* Hex转换
*
* @param bt
* @return
*/
public static String byteToHexString(byte[] bt) {
StringBuilder stringBuilder = new StringBuilder("");
for (byte aSrc : bt) {
int v = aSrc & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
}
服务端
SecretKeyFilter.java
import com.odianyun.cc.business.utils.SpringContextUtil;
import com.odianyun.cc.business.write.manage.IOccSecretKeyManage;
import com.odianyun.cc.model.dto.OccSecretKeyDTO;
import com.odianyun.cc.model.util.SecretUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
public class SecretKeyFilter implements Filter{
private static final Logger logger = LoggerFactory.getLogger(SecretKeyFilter.class);
private static final String EXCLUDE_CONFIG_NAME = "excludeURL";
private SecretKeyFilterConfig secretKeyFilterConfig;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
if (logger.isDebugEnabled()) {
logger.debug("--------------------SecretKeyFilter-------------init ");
}
String excludeConfig = filterConfig.getInitParameter(EXCLUDE_CONFIG_NAME);
this.secretKeyFilterConfig = SecretKeyFilterConfig.getInstance(excludeConfig);
}
private String getRequetUriExcludeContextPath(HttpServletRequest req) {
String requestUrl = req.getRequestURI();
String contextPath = req.getContextPath();
String reqPath = requestUrl.replace(contextPath, "");
while(reqPath.startsWith("//")){
reqPath = reqPath.replaceFirst("//","/");
}
if (logger.isDebugEnabled()) {
logger.debug("requestUrl={},contextPath={},reqPath={}", requestUrl, contextPath, reqPath);
}
return reqPath;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
String requestUri = this.getRequetUriExcludeContextPath(req);
if (this.secretKeyFilterConfig.match(requestUri)){
chain.doFilter(request, response);
return;
}
String envCode = req.getHeader("envCode");
String nsCode = req.getHeader("nsCode");
if(StringUtils.isNotBlank(envCode) && StringUtils.isNotBlank(nsCode)){
OccSecretKeyDTO dto = new OccSecretKeyDTO();
dto.setEnvCode(envCode);
dto.setNsCode(nsCode);
IOccSecretKeyManage occSecretKeyManage = SpringContextUtil.getBean(IOccSecretKeyManage.class);
try {
dto = occSecretKeyManage.selectOneSecretkey(dto);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
if(dto == null){
chain.doFilter(request, response);
return;
}
//签名校验 add by jdkleo @ 2017-03-21 11:06
ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(req);
String body = HttpHelper.getBodyString(requestWrapper);
String signature = req.getHeader("signature");//签名
String signatureString = SecretUtil.hmac256(body, dto.getSecretKey());//按原文进行签名计算
if (signatureString.equals(signature)){//比较服务器签名和客户端签名
chain.doFilter(requestWrapper, response);
return;
}
}
}
@Override
public void destroy() {
}
}
BodyReaderHttpServletRequestWrapper.java
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Enumeration;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
private final byte[] body;
public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
body = HttpHelper.getBodyString(request).getBytes(Charset.forName("UTF-8"));
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public int read() throws IOException {
return bais.read();
}
};
}
@Override
public String getHeader(String name) {
return super.getHeader(name);
}
@Override
public Enumeration getHeaderNames() {
return super.getHeaderNames();
}
@Override
public Enumeration getHeaders(String name) {
return super.getHeaders(name);
}
}
HttpHelper.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import javax.servlet.ServletRequest;
public class HttpHelper {
/**
* 获取请求Body
*
* @param request
* @return
*/
public static String getBodyString(ServletRequest request) {
StringBuilder sb = new StringBuilder();
InputStream inputStream = null;
BufferedReader reader = null;
try {
inputStream = request.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
}