繁体   English   中英

Google Apps Script - 如何登录和获取数据?

[英]Google Apps Script - how to login and fetch data?

介绍:
我非常缺乏经验,但最近我一直在尝试使用 Google Apps 脚本从网站访问一些数据。 但是,要访问数据,我必须登录该网站。 实际上之前有很多关于类似问题的帖子,但是直到我来到这个: 如何使用谷歌应用程序脚本获取 wordpress 管理页面之前,它们都没有太大帮助。 接受的答案提供了一种保存 cookie 并在第二个请求中再次发送它们的方法。 我基本上是将代码复制并粘贴到我自己的 GAS 文件中。 由于该帖子中的问题是登录 Wordpress,因此我先尝试了该方法,并且成功了。 我不得不删除检查响应代码的 if 语句,因为即使我输入了正确的组合,也会返回 200。 我不知道这只是帖子代码中的错误还是什么。 无论如何,我验证了我发出的第二个请求是否返回了信息,就像我已登录一样。

具体站点详情:
我试图登录的实际网站有一种奇怪的散列方法,我在任何其他登录页面上都没有看到过。 当您单击提交时,密码会在转到另一个页面之前很长时间更改为某些内容。 打开表单标签如下所示:

<form action="/guardian/home.html" method="post" name="LoginForm" target="_top" id="LoginForm" onsubmit="doPCASLogin(this);">

正如你所看到的,它有一个“onsubmit”属性,我相信它只会运行“doPCASLogin(this);” 提交表单时。 我决定通过在地址栏中输入 javascript 来玩转该页面。 我发现执行这样的命令(在输入我的用户名和密码后):

javascript: document.forms[0].submit();

没有用。 所以我在一个名为“md5.js”的javascript文件中找到了函数“doPCASLogin()”。 我相信 md5 是某种哈希算法,但这并不重要。 “doPCASLogin()”的重要部分是这样的:

function doPCASLogin(form) {
   var originalpw = form.pw.value;
   var b64pw = b64_md5(originalpw);
   var hmac_md5pw = hex_hmac_md5(pskey, b64pw)
   form.pw.value = hmac_md5pw;
   form.dbpw.value = hex_hmac_md5(pskey, originalpw.toLowerCase())
   if (form.ldappassword!=null) {
     form.ldappassword.value = originalpw;
   }
}

还有一些其他的东西,但我发现我的登录无关紧要。 很明显,这只是使用“pskey”(存储在隐藏的输入中,每次重新加载时不同)作为密钥通过另一个函数运行密码几次,并将这些输入到原始表单(“dbpw”和“ldappassword”是隐藏的输入,而“pw”是可见的密码输入)。 执行此操作后,它会提交。 我找到了另一个“hex_hmac_md5()”函数,它实际上连接到一大堆其他函数来散列密码。 无论如何,这并不重要,因为我可以从我在地址栏中键入的 javascript 调用“hex_hmac_md5()”。 这是我想出的工作代码,我只是为了可读性而打破了线路:

javascript:
document.forms['LoginForm']['account'].value="username";
document.forms['LoginForm']['pw'].value="hex_hmac_md5(pskey, b64_md5('password');)";
document.forms['LoginForm']['ldappassword'].value="password";
document.forms['LoginForm']['dbpw'].value="hex_hmac_md5(pskey, 'password')";
document.forms['LoginForm'].submit();

无论你在哪里看到“用户名”或“密码”,这只是意味着我在这些地方输入了我的用户名和密码,但显然我已经删除了它们。 当我发现这行得通时,我编写了一个小的 Chrome 扩展程序,当我访问网站时它会自动登录(登录过程很奇怪,所以 Chrome 不记得我的用户名和密码)。 那很好,但这不是我的最终目标。

困境:
在发现有关散列的所有这些之后,我尝试将所有这些值放入 GAS 文件中的 HTTP 有效负载中,尽管我怀疑它是否会起作用。 它没有,我怀疑这是因为这些值只是作为字符串被读取,而实际上并没有运行 javascript。 这是有道理的,因为运行实际的 javascript 可能是一个安全问题。 但是,为什么它会在地址栏中工作呢? 顺便提一下,我收到了一个 200 响应代码,而且似乎也发回了一个 cookie,尽管它可能无效。 当我阅读实际响应时,它又只是登录页面。

看到以下内容后,我还考虑尝试在自己的代码中复制整个功能: 如何以编程方式登录网站? ,但由于每次重新加载时“pskey”都不同,我认为散列必须使用第二个 UrlFetch 上的新键完成。 因此,即使我确实将所有功能复制到我的 GAS 文件中,我也不认为我可以成功登录,因为在实际发送请求之前,我需要知道将为特定请求生成的“pskey”,即是不可能。 唯一可行的方法是,如果我能以某种方式维护一页并在发送数据之前阅读它,但我不知道如何使用 GAS 做到这一点。

编辑:我发现了另一个名为“contextData”的输入,它与页面加载时的“pskey”相同。 但是,如果我登录一次并查看使用 Chrome 开发人员工具发出的 POST 请求,我可以复制所有输入值,包括“contextData”,并且我可以再次发送另一个请求。 在地址栏中使用 javascript,它看起来像这样:

javascript:
document.forms['LoginForm']['account'].value="username";
document.forms['LoginForm']['pw'].value="value in field that browser sent once";
document.forms['LoginForm']['ldappassword'].value="password";
document.forms['LoginForm'['dbpw'].value="value in field that browser sent once";
document.forms['LoginForm'['contextData'].value="value in field that browser sent once";
document.forms['LoginForm'].submit();

我可以通过这种方式多次登录该网站,无论“pskey”是什么,因为我直接提交所有内容并且没有进行散列。 但是,这对我仍然不起作用,所以我有点卡住了。 我应该注意,我已经检查了其他隐藏的输入字段,即使清除了表单中的每个输入,我仍然可以使用上面的 javascript 成功登录。

问题:
- 假设我发送的代码被解释为字符串,我是否正确?
- 为什么我最近写的下面的新代码不起作用?
- 为了将来参考,我将如何使用 GAS 登录像 Google 这样的网站,其中在登录表单中发送随机生成的字符串,并且必须将其发回?

function getData() {
  var loginURL = 'login page';
  var dataURL = 'page with data';
  var loginPayload = {
     'account':'same as in previous code block',
     'pw':"same as in previous code block",
     'ldappassword':'same as in previous code block',
     'dbpw':"same as in previous code block",
     "contextData":"same as in previous code block",
  };
  var loginOptions = {'method':'post','payload':loginPayload,'followredirects':false};
  var loginResponse = UrlFetchApp.fetch(loginURL,loginOptions);

  var loginHeaders = loginResponse.getAllHeaders();
  var cookie = [loginResponse.getAllHeaders()["Set-Cookie"]];
  cookie[0] = cookie[0].split(";")[0];
  cookie = cookie.join(";");

  var dataHeaders = {'Cookie':cookie};
  var dataOptions = {'method':'get','headers':dataHeaders};
  var dataResponse = UrlFetchApp.fetch(dataURL,dataOptions);

  Logger.log(dataResponse);
}

我在任何其他登录页面上都没有看到过的某种奇怪的散列方法

此登录使用基于base-64 编码密码的众所周知的MD5 散列算法(值得注意的是,它使用相同的密码,但小写,用于看似数据库访问dbpw ,并且可以选择发送纯文本 (!) 版本LDAP登录密码)。

在实际发送请求之前知道将为特定请求生成的“pskey”,这是不可能的

pskey只是存储用于计算 HMAC 签名的密钥。 没有什么可以阻止您对其进行硬编码、从磁盘读取、生成它或随时随地从远程获取(显然,在计算之前)。

运行实际的 javascript 可能是一个安全问题

尽管运行不受信任的 JavaScript 代码确实是一个安全问题,但在您的情况下根本不是这样。 有关原因的详细解释,请参阅下一点。 您应该做的是在将散列函数分配给loginPayload属性之前实际运行散列函数(在 2020 年, Utilities服务提供了您在这方面所需的一切)。

假设我发送的代码被解释为字符串,我是否正确?

您放在引号中的所有内容(单引号或双引号)都被视为字符序列。 这不是 Google Apps Script 的工作方式,这就是 ECMAScript(它所基于的)的工作方式。 为了在字符串“内部”执行函数,您需要使用eval ,但请永远不要这样做

现在,在 2020 年,我花了一些时间来记住javascript:协议的含义。 这是您的代码首先执行的唯一原因 - 您明确告诉浏览器接下来是要执行的 JavaScript 代码。 如果有人看到这个:请不要再使用它了。

Google Apps Script 是服务器端代码,不会在浏览器环境中执行,因此,即使您确实使用了该协议,也不会产生任何影响,因为没有进行评估。

为什么我最近写的下面的新代码不起作用?

由于上述所有原因。

以供将来参考,我将如何使用 GAS 登录像 Google 这样的网站,其中在登录表单中发送随机生成的字符串,并且必须将其发回?

如果您在谈论 OAuth / OAuth2.0 身份验证协议,这里有一个专门用于此目的的官方认可的库

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM