当前位置: 首页 > 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.jsqmd.com/news/101077/

相关文章:

  • MHT-FE710 光纤组合导航系统技术指南:高精度导航的多接口适配与工程实践
  • 吹爆FreeBuds SE4 ANC的新音效 | 浅聊体验
  • 网盘直链解析终极方案:彻底告别下载限制的完整指南
  • 纪念币预约神器:3步实现高效自动预约的终极指南
  • Unity翻译插件终极指南:3步实现游戏无障碍体验
  • Google Drive高效下载终极指南:解锁无限下载潜力
  • vue中的props详解
  • A module that was compiled using NumPy 1.x cannot be run in NumPy 2.0.2 as it may crash. To support
  • tlias的部门的增删改查操作
  • LangChain构建智能文档分析系统的7个核心技术模块
  • NVIDIA TensorRT-LLM高性能推理框架解析
  • LobeChat能否支持星际语言翻译?外星文明假说沟通模型构建
  • 问题:本地启动项目,想让其他人在他们自己的电脑也能访问该项目。需要怎么配置代理?
  • 生产环境Helm实战:从零搭建高可用应用发布流水线
  • 纪念币预约自动化终极指南:高效提升预约成功率
  • 跟着铁头山羊学STM32单片机(串口篇)
  • Unity游戏翻译终极方案:XUnity.AutoTranslator技术深度解析
  • 10分钟构建verification failed:(0x1a)错误监控原型
  • Helm vs 原生K8s:部署效率对比实测
  • 零基础入门:VSCode和Anaconda的Python开发环境搭建
  • LobeChat儿童故事创作助手趣味应用
  • LobeChat错误码对照表:快速定位请求失败原因
  • CallerRunPolicy vs AbortPolicy:性能对比与选择指南
  • 用XMRig快速验证挖矿算法原型
  • 企业级应用中的数据库连接异常处理实战
  • 强调智慧实验室管理系统的设计要考虑的几项问题
  • LobeChat能否定制品牌LOGO?白标解决方案
  • 如何用AI自动生成HTTP抓包工具?快马平台实战
  • LobeChat适配LoRA微调模型的方法与注意事项
  • 用D盾快速构建安全检测原型系统