HMAC计算
HMAC值通过加盐哈希运算获取,盐值(salt/secret)由第三方自行生成。
可以用下列命令来产生:openssl rand -base64 64
生成后需保存在业务系统的服务都,同时在文档中台server配置,盐值需要谨慎保管,防止暴露。
HMAC计算步骤:
- 拼接URL。URL不包含请求协议、请求主机信息以及请求参数HMAC
- 第三方服务调用第三方server生成HMAC值
- URL最后拼接请求参数HMAC
- 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();
}}