有学有练才叫学习:学而不思则罔,思而不学则殆:学而不习,纸上谈兵,习而不进,画地为牢!

header authorization(使用HTTP头Authorization保障安全通信)

开发者资讯 炮渣日记 2周前 (11-19) 31次浏览 已收录 0个评论 扫描二维码

信息安全:

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(应用秘钥)、校验传输数据的完整性,从而达到真实可靠的目标。

下图为通信过程简述:

header authorization(使用HTTP头Authorization保障安全通信)

核心代码:

package com.what21.apps.json.author;

import lombok.Data;
import lombok.ToString;
import org.apache.commons.codec.binary.Base64;

import java.io.ByteArrayInputStream;
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);
    }
}
喜欢 (0)
炮渣日记
关于作者:
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址