如何解决具有摘要身份验证问题的 Google App Script 提取请求
我正在尝试使用 GAS 的 UrlFetchApp 从 HIK Vision 的摄像头系统 DVR 中检索一些信息。我能够使用 Postman 执行成功的请求,但无法将其与 Google App Script 的 UrlFetchApp.fetch 一起使用。我确认我的摘要计算是正确的。我通过将 GAS 中的 nonce、cnonce、qop 等值替换为 Postman 中的值并获得与 Postman 相同的响应字符串来做到这一点。请参阅下面的邮递员图片:
Postman 收到 200 条响应以及我需要的所有数据。
我的应用程序的工作方式是发送第一个请求并获得 401 响应。然后它发送第二个请求,并带有根据从第一个请求接收到的数据计算出的 auth 标头。无论我做什么,我总是得到 401。我在标题属性等中使用了双引号。
代码如下:
function getRecordedDaysCount(){
const url = 'my_server_url';
const userName = 'user';
const pass = "password";
const uri = "/ISAPI/ContentMgmt/record/tracks/101/dailydistribution";
const method = "POST"
const updatedUrl = url + uri;
let year = '2021';
let month = '03';
//payload required by the server for this request
let payload = '<?xml version: "1.0" encoding="utf-8"?><trackDailyParam><year>' + year + '</year><monthOfYear>' + month + '</monthOfYear></trackDailyParam>';
let options = {
"method" : method,"muteHttpExceptions": true,"headers":{
"Accept": "application/xml,text/plain,*/*",}
}
let data = UrlFetchApp.fetch(updatedUrl,options);
if(data.getResponseCode() == 401){
let wwwAuthenticate = data.getAllHeaders()["WWW-Authenticate"];
// Example WWWAuthenticate
// "Digest realm="493b21e13dddb4ef7745edaa",domain="::",qop="auth",// nonce="17fbf10682dc4a7ceb04206cbcd95d8d:1616709300571",opaque="",algorithm="MD5",stale="FALSE""
let authData = wwwAuthenticate.split(',');
let authType = authData[0].split(' ')[0]; // Digest
if(authType === "Digest"){
let realm = authData[0].split('"')[1]; // "493b21e13dddb4ef7745edaa"
let qop=authData[2].split('"')[1]; // "auth"
let nonce = authData[3].split('"')[1]; // "17fbf10682dc4a7ceb04206cbcd95d8d:1616709300571"
let algorithm = authData[5].split('"')[1]; // "MD5"
let nc="00000001";
let cnonce= new Date().getTime().toString(16);
let hash1 = signMD5(userName +':'+ realm +':'+ pass);
let hash2 = signMD5(method+':'+ uri);
let response = signMD5(hash1+':'+nonce+':'+nc+':'+cnonce+':'+qop+':'+hash2);
let digestAuth = "Digest username=\"" + userName + "\"" +
",realm=\"" + realm + "\"" +
",nonce=\"" + nonce + "\"" +
",uri=\"" + uri + "\"" +
",qop=auth" +
",nc=" + nc +
",algorithm=\"MD5\"" +
",cnonce=\"" + cnonce + "\"" +
",response=\"" + response + "\"";
let headers = {
"Content-Type": "text/plain",// copied from Postman
"Accept-Encoding": "gzip,deflate,br",// copied from Postman
"Authorization": digestAuth,}
let options = {
"method" : method,"headers": headers,"payload": (payload)
}
logUrlFetch(updatedUrl,options);
}
}
}
function signMD5(message){
let signature = Utilities.computeDigest(
Utilities.DigestAlgorithm.MD5,message,Utilities.Charset.UTF_8);
let signatureStr = '';
for (i = 0; i < signature.length; i++) {
let byte = signature[i];
if (byte < 0)
byte += 256;
let byteStr = byte.toString(16);
// Ensure we have 2 chars in our byte,pad with 0
if (byteStr.length == 1) byteStr = '0'+byteStr;
signatureStr += byteStr;
}
Logger.log(signatureStr);
return signatureStr;
}
function logUrlFetch(url,opt_params) {
let params = opt_params || {};
params.muteHttpExceptions = true;
let request = UrlFetchApp.getRequest(url,params);
Logger.log('Request: >>> ' + JSON.stringify(request));
let response = UrlFetchApp.fetch(url,params);
Logger.log('Response Code: <<< ' + response.getResponseCode());
Logger.log('Response text: <<< ' + response.getContentText());
if (response.getResponseCode() >= 400) {
throw Error('Error in response: ' + response);
}
return response;
}
这些是我得到的日志:
- 第一个请求后的标头
- 在第二个请求后登录
我多次比较了 Postman 和我的应用程序中的标头,它们大体相同但存在一些差异。 UrlFetchApp.fetch 向请求添加了一些标头,但是我也在 Postman 中添加了它们,它仍然有效,所以我得出结论,这些额外的标头不是问题。此外,UrlFetchApp.fetch 将请求方法发送为“post”(小写),邮递员使用全部大写 - 'POST'。 http方法是Digest HA2计算的一部分,区分大小写。这是我对为什么我的请求不起作用的唯一想法。我将我的应用程序的方法更改为小写“post”以用于摘要计算和标题,但这没有帮助。
除了 UrlFetchApp.fetch 之外,还有其他方法可以在 Google App Script 中发送请求吗? 非常感谢!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。