在独立的Python脚本中向Google认证的正确机制是什么?

2024-05-14 03:44:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我从Gmail中提取了一些电子邮件地址。这是一个在cron作业中运行的简单Python脚本,基于Python gdata library(当前为v2.0.18)。在

截至本月早些时候,由于Googledeprecating the ClientLogin protocol,这项工作不再有效。产生的错误如下所示:

{'status': 401, 'body': '<?xml version="1.0" encoding="UTF-8"?>\n<errors xmlns="http://schemas.google.com/g/2005">\n <error>\n  <domain>GData</domain>\n  <code>required</code>\n  <location type="header">Authorization</location>\n  <internalReason>Login Required</internalReason>\n </error>\n</errors>\n', 'reason': 'Unauthorized'}

我知道这将要到来,并在其他地方处理它(如AppEngine应用程序),但忘记了我必须转换这个脚本。现在我在这里,我发现我不知道我该怎么做。在

我找到的所有参考资料,比如googleapps开发者博客上的here,或者StackOverflow上的here和{a5},都表明解决方案是使用OAuth2Token。但是,这需要来自googleapi控制台的客户机id和客户机机密,后者与应用程序绑定在一起。我没有申请。我只想验证一下我的脚本。在

有人能建议在一个独立的脚本中正确的方法吗?或者是我运气不好,再也没有办法完成这个任务了?在

这是现有联系人代码的核心:

^{pr2}$

理想情况下,我希望用其他机制替换client.ClientLogin(),该机制使用gdata保留其余代码。另外,如果gdata不能真正做到这一点,我愿意转换成其他提供类似功能的库。在


Tags: 代码脚本应用程序客户机heredomaincodelocation
2条回答

最终,使用curl编写一个shell脚本要比使用curl简单得多 搞乱gdata库。正如预期的那样,我能够 根据 OAuth2 Device Flow instructions。在

在完成验证过程后,我获得了所需的4个证书: 客户端id、客户端机密、访问令牌和刷新令牌。 根据谷歌的文档,访问令牌最终会过期。你可以 通过请求令牌管理器刷新令牌来获取新的访问令牌。 当您这样做时,您显然得到了一个新的访问令牌,但是不是一个新的刷新 令牌。在

我在CREDENTIALS中存储客户机id和机密以及刷新令牌 JSON格式的文件。由于访问令牌会随着时间而变化,因此它存储在ACCESS文件中,也是JSON格式。在

脚本的重要部分如下所示:

#!/bin/ksh

CLIENT_ID=$(cat ${CREDENTIALS} | jq -r ".client_id")
CLIENT_SECRET=$(cat ${CREDENTIALS} | jq -r ".client_secret")
REFRESH_TOKEN=$(cat ${CREDENTIALS} | jq -r ".refresh_token")
ACCESS_TOKEN=$(cat ${ACCESS} | jq -r ".access_token")

CONTACTS_URL="https://www.google.com/m8/feeds/contacts/default/full?access_token=${ACCESS_TOKEN}&max-results=5000&v=3.0"
ERROR=$(curl  show-error  silent  fail "${CONTACTS_URL}" -o ${CONTACTS_XML} 2>&1)
RESULT=$?
if [[ ${RESULT} -eq 0 ]]
then
   cat ${CONTACTS_XML} | grep 'gd:email' | sed 's/^.*address="//g' | sed 's/".*$//g' | tr '[:upper:]' '[:lower:]' | sort | uniq
elif [[ ${RESULT} -eq 22 ]]
then
   echo "${ERROR}" | grep -q "401"
   if [[ $? -eq 0 ]]
   then
      TOKEN_URL="https://www.googleapis.com/oauth2/v3/token"
      REFRESH_PARAMS="client_id=${CLIENT_ID}&client_secret=${CLIENT_SECRET}&refresh_token=${REFRESH_TOKEN}&grant_type=refresh_token"
      ERROR=$(curl  show-error  silent  fail  data "${REFRESH_PARAMS}" ${TOKEN_URL} -o ${REFRESH_JSON})
      RESULT=$?
      if [[ ${RESULT} -eq 0 ]]
      then
         ACCESS_TOKEN=$(cat ${REFRESH_JSON} | jq -r ".access_token")
         jq -n  arg access_token "${ACCESS_TOKEN}" '{"access_token": $access_token, }' > ${ACCESS}

         CONTACTS_URL="https://www.google.com/m8/feeds/contacts/default/full?access_token=${ACCESS_TOKEN}&max-results=5000&v=3.0"
         ERROR=$(curl  show-error  silent  fail "${CONTACTS_URL}" -o ${CONTACTS_XML} 2>&1)
         RESULT=$?
         if [[ ${RESULT} -eq 0 ]]
         then
            cat ${CONTACTS_XML} | grep 'gd:email' | sed 's/^.*address="//g' | sed 's/".*$//g' | tr '[:upper:]' '[:lower:]' | sort | uniq
         else
            print "Unexpected error: ${ERROR}" >&2
            exit 1
         fi
      else
         print "Unexpected error: ${ERROR}" >&2
         exit 1
      fi
   else
      print "Unexpected error: ${ERROR}" >&2
      exit 1
   fi
else
   print "Unexpected error: ${ERROR}" >&2
   exit 1
fi

这不是世界上最漂亮的东西,但我想找些又快又脏的东西,这很管用。在

Can someone please suggest the proper way to do this in a standalone script? Or am I out of luck and there's no mechanism to accomplish this any more?

再也没有像你现在使用的那种机制了。您必须设置一个Cloud Developer project并使用OAuth2,然后重写脚本。在

为了使它尽可能的面向未来,您可以切换到最新的Contacts API。有了这个API,您可以使用OAuth2 Device flow,这对您的用例来说可能更简单。在

不是你希望听到的答案,我知道,但我认为这是唯一的答案。在

相关问题 更多 >