当前位置: 首页 > news >正文

手写海康OpenApi签名规范,实现手动调用api(sdk:artemis-http-client)

1. 前言:

artemis-http-clientsdk 中提供获取门禁事件图片的方法,但实际图片访问地址为该响应的重定向地址
问题来了:虽然他提供了 sdk ,但没有办法通过 sdk 获取重定向的地址于是产生了本文,自己通过hutools的 httpUtil调用

2. 签名工具类

HikSignUtil 记得先引入一下 artemis-http-client

packagecom.lxsy.util;importcn.hutool.core.codec.Base64;importcn.hutool.crypto.digest.DigestUtil;importcn.hutool.crypto.digest.HMac;importcn.hutool.crypto.digest.HmacAlgorithm;importjava.nio.charset.StandardCharsets;importjava.time.ZoneOffset;importjava.time.ZonedDateTime;importjava.time.format.DateTimeFormatter;importjava.util.HashMap;importjava.util.Map;/** * 海康 OpenAPI 签名工具类 * 签名算法:HmacSHA256 + Base64 */publicclassHikSignUtil{privatestaticfinalDateTimeFormatterRFC_1123_FORMATTER=DateTimeFormatter.RFC_1123_DATE_TIME.withZone(ZoneOffset.UTC);/** * 生成请求头(包含签名) * * @param appKey 应用Key * @param appSecret 应用Secret * @param url 请求的相对路径(如 /artemis/api/acs/v1/event/pictures) * @param body 请求体(JSON字符串) * @return 包含签名的请求头Map */publicstaticMap<String,String>buildHeaders(StringappKey,StringappSecret,Stringurl,Stringbody){// Content-MD5:请求体的MD5值,Base64编码StringcontentMd5=Base64.encode(DigestUtil.md5(body));// Date 头(RFC1123)Stringdate=RFC_1123_FORMATTER.format(ZonedDateTime.now(ZoneOffset.UTC));// 签名字符串拼接// httpHeaders = HTTP METHOD + "\n" + Accept + "\n" + Content-MD5 + "\n" + Content-Type + "\n" + Date + "\n"// customHeaders = "x-ca-key" + ":" + appKey + "\n"// signString = httpHeaders + customHeaders + urlStringBuildersignBuilder=newStringBuilder();signBuilder.append("POST").append("\n");// HTTP METHODsignBuilder.append("*/*").append("\n");// AcceptsignBuilder.append(contentMd5).append("\n");// Content-MD5signBuilder.append("application/json").append("\n");// Content-TypesignBuilder.append(date).append("\n");// DatesignBuilder.append("x-ca-key:").append(appKey).append("\n");// customHeaderssignBuilder.append(url);// urlStringsignString=signBuilder.toString();// 使用 HmacSHA256 算法计算签名HMachmac=newHMac(HmacAlgorithm.HmacSHA256,appSecret.getBytes(StandardCharsets.UTF_8));Stringsignature=Base64.encode(hmac.digest(signString));// 构建请求头Map<String,String>headers=newHashMap<>();headers.put("Accept","*/*");headers.put("Content-Type","application/json");headers.put("Content-MD5",contentMd5);headers.put("Date",date);headers.put("x-ca-key",appKey);headers.put("x-ca-signature",signature);headers.put("x-ca-signature-headers","x-ca-key");returnheaders;}}

3. 使用

示例1

protectedstaticfinalArtemisConfigartemisConfig=newArtemisConfig("192.XX.13.XX:443","123","123");/** * 使用自建 HttpClient 调用海康接口,便于排查网络/签名问题 */publicstaticPageResponseResult<EventInfoDto>getEventListWithHttpClient(EventsRequesteventsRequest)throwsException{if(eventsRequest==null){eventsRequest=newEventsRequest();}Stringurl="/artemis/api/acs/v2/door/events";StringfullUrl="https://"+artemisConfig.getHost()+url;Stringbody=JSON.toJSONString(eventsRequest);Map<String,String>headers=HikSignUtil.buildHeaders(artemisConfig.getAppKey(),artemisConfig.getAppSecret(),url,body);try(CloseableHttpClienthttpClient=createHttpClient(false)){HttpPosthttpPost=newHttpPost(fullUrl);headers.forEach(httpPost::setHeader);httpPost.setEntity(newStringEntity(body,ContentType.APPLICATION_JSON));try(CloseableHttpResponseresponse=httpClient.execute(httpPost)){intstatus=response.getStatusLine().getStatusCode();StringrespBody=response.getEntity()==null?null:EntityUtils.toString(response.getEntity());if(status==HttpStatus.SC_OK){returncheckResp(respBody,newTypeReference<PageResponseResult<EventInfoDto>>(){});}thrownewException("获取事件列表失败,状态码: "+status+", 响应: "+respBody);}}}

示例2

protectedstaticfinalArtemisConfigartemisConfig=newArtemisConfig("192.XX.13.XX:443","123","123");publicstaticStringpictures(StringsvrIndexCode,StringpicUri)throwsException{Stringurl="/artemis/api/acs/v1/event/pictures";StringfullUrl="https://"+artemisConfig.getHost()+url;// 构建请求体PicturesRequestrequest=newPicturesRequest(svrIndexCode,picUri);Stringbody=JSON.toJSONString(request);// 使用签名工具生成请求头Map<String,String>headers=HikSignUtil.buildHeaders(artemisConfig.getAppKey(),artemisConfig.getAppSecret(),url,body);try(CloseableHttpClienthttpClient=createHttpClient(false)){HttpPosthttpPost=newHttpPost(fullUrl);headers.forEach(httpPost::setHeader);httpPost.setEntity(newStringEntity(body,ContentType.APPLICATION_JSON));try(CloseableHttpResponseresponse=httpClient.execute(httpPost)){intstatus=response.getStatusLine().getStatusCode();if(status==HttpStatus.SC_MOVED_TEMPORARILY||status==HttpStatus.SC_MOVED_PERMANENTLY||status==HttpStatus.SC_SEE_OTHER||status==HttpStatus.SC_TEMPORARY_REDIRECT||status==HTTP_STATUS_PERMANENT_REDIRECT){HeaderlocationHeader=response.getFirstHeader("Location");if(locationHeader!=null&&StrUtil.isNotBlank(locationHeader.getValue())){returnlocationHeader.getValue();}thrownewException("302重定向但未获取到Location头");}StringrespBody=response.getEntity()==null?null:EntityUtils.toString(response.getEntity());thrownewException("获取图片失败,状态码: "+status+", 响应: "+respBody);}}}
http://www.zskr.cn/news/111852.html

相关文章:

  • A module that was compiled using NumPy 1.x cannot be run in NumPy 2.0.2 as it may crash. To support
  • tlias的部门的增删改查操作
  • 生产环境Helm实战:从零搭建高可用应用发布流水线
  • 问题:本地启动项目,想让其他人在他们自己的电脑也能访问该项目。需要怎么配置代理?
  • LobeChat能否支持星际语言翻译?外星文明假说沟通模型构建
  • LobeChat儿童故事创作助手趣味应用
  • LobeChat错误码对照表:快速定位请求失败原因
  • LobeChat能否定制品牌LOGO?白标解决方案
  • 强调智慧实验室管理系统的设计要考虑的几项问题
  • 如何用AI自动生成HTTP抓包工具?快马平台实战
  • java计算机毕业设计书网 纸电融合知识共享平台 全域图书流转中枢
  • 如何快速实现Unity游戏自动翻译?XUnity.AutoTranslator终极解决方案
  • 聚焦能源招采,中国能源招标网开启绿色新征程!
  • 2025年河南工业大学2025新生周赛(8)
  • 高并发时代的“确定性”挑战——为何稳定性正在成为 JVM 的下一场核心竞争?
  • 唯一屹立的厂商: Elastic 在 2025 AV-Comparatives 测试中的全面胜出
  • 基于VirtualBox使用ISO创建Linux镜像
  • 什么是静态住宅ip,跨境电商为什么要用静态住宅ip
  • 如何在Android中使用StateFlow和MutableStateFlow?
  • 用于氧化石墨烯的多模态表征与激光还原图案化的共聚焦显微技术
  • 剧本杀剧情设计:LobeChat构造悬疑故事情节
  • 盲盒一番赏小程序开发:解锁千亿级潮玩市场的技术密码
  • 场馆预约小程序开发:解锁 “预约经济” 的高效解决方案
  • 应用材料 0195-02529
  • 大模型学习笔记
  • 大模型中 System Prompt 与 Instruction 的区别
  • FreeSWITCH 实用工具集(个人开发整理)
  • 3CTEST解析8/20μs冲击电流测试的多样性挑战与冲击电流发生器选型策略
  • AMAT 0190-27084
  • 【毕业设计】基于JavaWeb的智慧养老院管理系统的设计与实现(源码+文档+远程调试,全bao定制等)