跳到主要内容

HMAC计算

HMAC值通过加盐哈希运算获取,盐值(salt/secret)由第三方自行生成。

可以用下列命令来产生:openssl rand -base64 64

生成后需保存在业务系统的服务都,同时在文档中台server配置,盐值需要谨慎保管,防止暴露。

HMAC计算步骤:

  1. 拼接URL。URL不包含请求协议、请求主机信息以及请求参数HMAC
  2. 第三方服务调用第三方server生成HMAC值
  3. URL最后拼接请求参数HMAC
  4. iframe或者新标签页打开URL

新标签页打开编辑页面案例

前端代码

const userinfo = {  
id: 'test-1',
display_name: 'test-1',
email: 'test-1@zOffice.com'
}

const userinfoStr = btoa(JSON.stringify(userinfo));

const path = `/docs/app/driver-callback?repo=thirdparty&docId=kyKtKHsbShsK&action=edit&userinfo=${userinfoStr}`;
const host = 'http://zOfficeServer:8001`;

// 调用第三方API获取HMAC值
const pathWithHmac = axios.get(`http://3rd-party/getPathWithHmac?path=${path}`);

window.open(`${host}${pathWithHmac}`);

后端代码

import org.springframework.web.bind.annotation.GetMapping;  
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

@RestController
@Slf4j
public class HmacController {

@GetMapping("/getPathWithHmac")
@ResponseBody

public static String getHmac(String path) throws NoSuchAlgorithmException, InvalidKeyException, URISyntaxException {

StringBuilder builder = new StringBuilder(path);

builder.append("&ts=").append(new Date().getTime());

String secret = "xxxxxxxx"; //文档中台前端集成密钥,请勿在前端使用,避免泄漏

SecretKeySpec hmacSHA256 = new SecretKeySpec(secret.getBytes(), "HmacSHA256");

Mac mac = Mac.getInstance("HmacSHA256");

mac.init(hmacSHA256);

URI uri = new URI(builder.toString());

String reqUrl = uri.getRawPath() + "?" + uri.getRawQuery();

mac.update(reqUrl.getBytes(StandardCharsets.UTF_8));

String hmac = String.format("%064x", new BigInteger(1, mac.doFinal()));

builder.append("&HMAC=").append(hmac);

return builder.toString();

}}