信息安全:
ISO(国际标准化组织)定义,为数据处理系统建立和采用的技术、管理上的安全保护,为的是保护计算机硬件、软件、数据不因偶然和恶意的原因而遭到破坏、更改和泄露。
主要包括以下五方面的内容:需保证信息的保密性、真实性、完整性、未授权拷贝和所寄生系统的安全性。
本节说明的是:Web/互联网,HTTP通信过程中,通信时数据的真实性和完整性。
HTTP认证:
HTTP请求,基本认证:
HTTP协议中,把”用户名+:+密码”Base64编码后的字符串放在http request的header Authorization中发送给服务端, 这种方式叫:HTTP基本认证(Basic Authentication);
HTTP请求, OAuth 认证:
OAuth对于HTTP来说,在Authorization header中放的是一个token。
HTTP请求,Authorization自定义认证:
HTTP协议中,在Authorization header中放的是一个自定义的: “字符串” 。
系统对接(多个应用系统):
出于业务上的需要,系统就需要对接,在多个系统对接之时,往往有会有一个系统负责整合其它的各个系统,通常这个系统会为其他的系统生成:appId(应用ID)、appKey(应用秘钥)、communicationKey(通信key),用以标识其它系统身份(哪个系统)以及相互访问时之间的加解密约定;
那么,针对系统之间通信(HTTP协议)时数据的真实性和完整性,本文采用了: Authorization自定义认证 ,使得系统在通信之时,每次调用都去验证相应的appKey(应用秘钥)、校验传输数据的完整性,从而达到真实可靠的目标。
下图为通信过程简述:
核心代码:
package com.what21.apps. JSON .author;
import lombok.Data;
import lombok.ToString;
import org.apache.commons.codec.binary.Base64;
import java.io. byte ArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
@Data
@ToString
public class HttpAuthorizationBuilder {
private static final String AUTHOR_METHOD = "http-body-sign";
// AppId
private String appId;
// AppKey
private String appKey;
// Timestamp
private String timestamp;
// Nonce
private String nonce;
// Signature
private String signature;
// 请求内容
private String requestBody;
/**
* @param requestBody
* @return
*/ public String toAuthorizationString(String requestBody) throws Exception {
this.setRequestBody(requestBody);
// Timestamp
String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
this.setTimestamp(timestamp);
// Nonce
String nonce = Math.abs(UUID.randomUUID().getMostSignificantBits()) + "";
this.setNonce(nonce);
// 内容sha256Hex运行
byte[] data = requestBody.getBytes(Charset.forName("UTF-8"));
InputStream input = new ByteArrayInputStream(data);
String bodyDigest = sha256Hex(input);
// 签名
String str1_C = appId + timestamp + nonce + bodyDigest;
byte[] localSignature = hmacSHA256(str1_C.getBytes(), appKey.getBytes());
String localSignatureStr = Base64.encodeBase64String(localSignature);
this.setSignature(localSignatureStr);
// 返回
return (AUTHOR_METHOD + " AppId=" + """ + appId + """ + ", Timestamp=" + """ + timestamp + """ + ", Nonce=" + """ + nonce + """ + ", Signature=" + """ + localSignatureStr + """);
}
/**
* 校验签名
*
* @param requestBody
* @return
* @throws Exception
*/ private boolean verify(String requestBody) throws Exception {
// 内容sha256Hex运行
byte[] data = requestBody.getBytes(Charset.forName("UTF-8"));
InputStream input = new ByteArrayInputStream(data);
String bodyDigest = sha256Hex(input);
// 签名
String str1_C = this.appId + this.timestamp + this.nonce + bodyDigest;
byte[] localSignature = hmacSHA256(str1_C.getBytes(), appKey.getBytes());
String localSignatureStr = Base64.encodeBase64String(localSignature);
if (this.signature.equals(localSignatureStr)) {
return true;
}
return false;
}
/**
* 进行加密
*
* @param input
* @return 加密后的结果
*/ private static String sha256Hex(InputStream input) {
try {
return org.apache.commons.codec.digest.DigestUtils.sha256Hex(input);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* @param data
* @param key
* @return
* @throws Exception
*/ public static byte[] hmacSHA256(byte[] data, byte[] key) throws Exception {
String algorithm = "HmacSHA256";
javax .crypto.Mac mac = javax.crypto.Mac.getInstance(algorithm);
mac.init(new javax.crypto.spec.SecretKeySpec(key, algorithm));
return mac.doFinal(data);
}
/**
* 【银联】open-body-sig方式
* <p>
* open-body-sig方式获取到Authorization 的值
*
* @param appId
* @param appKey
* @param body
* @return
* @throws Exception
*/ public String getOpenBodySig(String appId, String appKey, String body) throws Exception {
// eg:20190227113148
String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
// eg:be46cd581c9f46ecbd71b9858311ea12
String nonce = UUID.randomUUID().toString().replace("-", "");
byte[] data = body.getBytes("UTF-8");
// System.out.println("data:n" + body);
InputStream input = new ByteArrayInputStream(data);
// eg:d60bc3aedeb853e2a11c0c096baaf19954dd9b752e48dea8e919e5fb29a42a8d
String bodyDigest = sha256Hex(input);
// System.out.println("bodyDigest:n" + bodyDigest);
String str1_C = appId + timestamp + nonce + bodyDigest; // eg:f0ec96ad2c3848b5b810e7aadf369e2f + 20190227113148 + be46cd581c9f46ecbd71b9858311ea12 + d60bc3aedeb853e2a11c0c096baaf19954dd9b752e48dea8e919e5fb29a42a8d
// System.out.println("str1_C:" + str1_C);
//System.out.println("appKey_D:n" + appKey);
byte[] localSignature = hmacSHA256(str1_C.getBytes(), appKey.getBytes());
String localSignatureStr = Base64.encodeBase64String(localSignature); // Signature
// System.out.println("Authorization:n" + "OPEN-BODY-SIG AppId=" + """ + appId + """ + ", Timestamp=" + """ + timestamp + """ + ", Nonce=" + """ + nonce + """ + ", Signature=" + """ + localSignatureStr + ""n");
return ("OPEN-BODY-SIG AppId=" + """ + appId + """ + ", Timestamp=" + """ + timestamp + """ + ", Nonce=" + """ + nonce + """ + ", Signature=" + """ + localSignatureStr + """);
}
/**
* @param appId
* @param appKey
* @param authorizationString
* @param requestBody
* @return
*/ public static HttpAuthorizationBuilder parse(String appId, String appKey, String authorizationString, String requestBody) {
if (appId == null || appKey == null || authorizationString == null || requestBody == null) {
return null;
}
if (!authorizationString.startsWith(AUTHOR_METHOD)) {
return null;
}
authorizationString = authorizationString.substring(AUTHOR_METHOD.length() + 1);
String[] arrayString = authorizationString.split(", ");
if (arrayString == null || arrayString.length != 4) {
return null;
}
String parseAppId = "AppId";
String parseTimestamp = "Timestamp";
String parseNonce = "Nonce";
String parseSignature = "Signature";
for (String string : arrayString) {
if (string.startsWith(parseAppId)) {
parseAppId = string.substring(parseAppId.length() + 2, string.length() - 1);
} else if (string.startsWith(parseTimestamp)) {
parseTimestamp = string.substring(parseTimestamp.length() + 2, string.length() - 1);
} else if (string.startsWith(parseNonce)) {
parseNonce = string.substring(parseNonce.length() + 2, string.length() - 1);
} else if (string.startsWith(parseSignature)) {
parseSignature = string.substring(parseSignature.length() + 2, string.length() - 1);
}
}
if (!appId.equals(parseAppId)) {
return null;
}
HttpAuthorizationBuilder httpAuthorizationBuilder = new HttpAuthorizationBuilder();
httpAuthorizationBuilder.setAppId(appId);
httpAuthorizationBuilder.setAppKey(appKey);
httpAuthorizationBuilder.setTimestamp(parseTimestamp);
httpAuthorizationBuilder.setNonce(parseNonce);
httpAuthorizationBuilder.setSignature(parseSignature);
httpAuthorizationBuilder.setRequestBody(requestBody);
// 验证
try {
if (!httpAuthorizationBuilder.verify(requestBody)) {
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return httpAuthorizationBuilder;
}
}
package com.what21.apps.json.author;
import com.alibaba.fastjson.JSON;
import java.util.HashMap;
import java.util.Map;
public class HttpAuthorizationBuilderTest {
public static void main(String[] args) throws Exception {
String appId = "appId";
String appKey = "appKey";
Map<String, Object> paramsMap = new HashMap<>();
paramsMap.put("id", "11111");
paramsMap.put("name", "名称");
// JSON签名
String requestBody = JSON.toJSONString(paramsMap);
// ============================================================================//
// 客户端HTTP header: Authorization [签名内容]
// ============================================================================//
HttpAuthorizationBuilder httpAuthorizationBuilder = new HttpAuthorizationBuilder();
httpAuthorizationBuilder.setAppId(appId);
httpAuthorizationBuilder.setAppKey(appKey);
String authorizationString = "";
try {
authorizationString = httpAuthorizationBuilder.toAuthorizationString(requestBody);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Authorization: " + authorizationString);
// ============================================================================//
// 服务端获取header解析验证Authorization
// ============================================================================//
HttpAuthorizationBuilder parseHttpAuthorizationBuilder = HttpAuthorizationBuilder.parse(appId, appKey, authorizationString, requestBody);
System.out.println("parseHttpAuthorizationBuilder :" + parseHttpAuthorizationBuilder);
}
}