1

底部的问题。

说明:我们正在尝试自动化 Cisco WebEx API 的不同方面。例如,从 API 获取所有设备和设备数据,然后将其呈现。这些设备可以显示连接状态、位置等等。这只是一个例子。

为了访问 WebEx API,您需要执行以下操作:

  1. 登录到您的企业帐户 ( https://developer.webex.com )。 在此处输入图像描述 然后输入您的密码: 在此处输入图像描述 在此之后,所有登录都通过以下方式重定向: 在此处输入图像描述

登录后,您可以使用文档并浏览 API 参考。在这里,您还可以尝试所有功能,这是使用个人令牌,据我所知,该令牌无法导出或在网站上的任何地方看到。您可以复制并使用它,但它会在 24 小时后过期。我想也许您可以使用 Python 登录您的帐户并不断刷新您的个人令牌,但这似乎不是一个好的解决方案。 在此处输入图像描述 因此,这让我想到:

  1. 创建一个集成,最终将为您提供 API 访问所需的令牌。因此,在这里我将展示如何创建集成,从而获得 API 访问所需的代码和令牌。 在此处输入图像描述 创建一个新应用,然后选择集成。 填写所有信息,然后单击添加集成。在此处输入图像描述 在此处输入图像描述 在此处输入图像描述

  2. 通过接受条款和条件生成用于请求令牌的代码。添加后,您将被带到应用程序集成页面,在这里您可以看到生成代码所需的所有信息,该代码将用于生成令牌集。 在此处输入图像描述 正如您在黑框中看到的,这是您需要将 URL 复制/粘贴到浏览器中,然后接受条款和条件,然后才能生成代码。结果如下: 在此处输入图像描述 复选框显示:“仅在请求新权限时询问” 单击接受后,您将被重定向到创建应用程序集成时指定的 URL。该网站不存在,但仍会在 URL 中显示代码: 在此处输入图像描述 复制代码,您现在可以使用以下代码和应用程​​序中的信息生成令牌集:

代码:

import requests, json

clientID = "C7aa20b0a57cae4127d1e08b15e3a94efacd5c7bb3e1a70ceed4308903a5b807b"
secretID = "b52db3ec6ad8622d0e0e01a0572bac982b214076308ea2e73a566fcf848c9369"
redirectURI = "https://www.your-oauth-website-here.dk/oauth"

def get_tokens(code):
    """Gets access token and refresh token"""
    print("code:", code)
    url = "https://api.ciscospark.com/v1/access_token"
    headers = {'accept':'application/json','content-type':'application/x-www-form-urlencoded'}
    payload = ("grant_type=authorization_code&client_id={0}&client_secret={1}&"
                    "code={2}&redirect_uri={3}").format(clientID, secretID, code, redirectURI)
    req = requests.post(url=url, data=payload, headers=headers)
    results = json.loads(req.text)
    print(results)
    access_token = results["access_token"]
    refresh_token = results["refresh_token"]
    return access_token, refresh_token

test = get_tokens("MWU4YTJmYTgtNjllMy00YjAzLTg0NTQtMTRkYTRiMmIxMzZkNWEzNzRkZDQtYTNk_PF84_33672567-1029-48fb-ba77-7fe2001ee897") # CODE

结果:

code: MWU4YTJmYTgtNjllMy00YjAzLTg0NTQtMTRkYTRiMmIxMzZkNWEzNzRkZDQtYTNk_PF84_33672567-1029-48fb-ba77-7fe2001ee897
{'access_token': 'OTU5MWNhYTItOWNiZC00MWU1LThlZDktNjRlYjI5OGIyYjNmNjI2M2U2MzgtNjAz_PF84_33672567-1029-48fb-ba77-7fe2001ee897', 'expires_in': 1209599, 'refresh_token': 'MGQ4MWRmMzAtYjQyNi00Mzk1LWI0MzAtMmRkMGIzMWQ3ZDVjNzQwZDM3N2YtMWIw_PF84_33672567-1029-48fb-ba77-7fe2001ee897', 'refresh_token_expires_in': 7775999}

如果您尝试使用相同的代码生成新的令牌对,则会显示以下错误:

{'message': "POST failed: HTTP/1.1 400 Bad Request (url = https://idbroker.webex.com/idb/oauth2/v1/access_token, request/response TrackingId = ROUTER_5FD9B9DA-FCB3-01BB-03C9-503F01C403C9, error = '(invalid_grant) Authorization code has been used.')", 'errors': [{'description': "POST failed: HTTP/1.1 400 Bad Request (url = https://idbroker.webex.com/idb/oauth2/v1/access_token, request/response TrackingId = ROUTER_5FD9B9DA-FCB3-01BB-03C9-503F01C403C9, error = '(invalid_grant) Authorization code has been used.')"}], 'trackingId': 'ROUTER_5FD9B9DA-FCB3-01BB-03C9-503F01C403C9'}
Traceback (most recent call last):
  File "c:/Python/test_shit.py", line 117, in <module>
    test = get_tokens("MWU4YTJmYTgtNjllMy00YjAzLTg0NTQtMTRkYTRiMmIxMzZkNWEzNzRkZDQtYTNk_PF84_33672567-1029-48fb-ba77-7fe2001ee897") # CODE
  File "c:/Python/test_shit.py", line 113, in get_tokens
    access_token = results["access_token"]
KeyError: 'access_token'

问题:令牌有效性设置如下:

  • 令牌:14 天到期。
  • 刷新令牌:90 天到期。

在此期间之后,您将必须完成创建新代码的过程,然后请求一组新的令牌。

我正在努力了解如何在 Red Hat Linux 系统上仅使用 Python 2.7.5 和 CLI 界面来自动化获取新代码的过程。

我曾尝试使用请求库打开并单击接受,但我没有任何成功。

这是我尝试通过请求会话在黑匣子中打开代码 URL 时发生的情况的示例:

>>> url = "https://webexapis.com/v1/authorize?client_id=C7aa20b0a57cae4127d1e08b15e3a94efacd5c7bb3e1a70ceed4308903a5b807b&response_type=code&redirect_uri=https%3A%2F%2Fwww.your-oauth-website-here.dk%2Foauth&scope=spark%3Aall%20spark%3Akms&state=set_state_here"
>>> with requests.Session() as s:
...     response = s.get(url)
...
>>> print(response.text)
<!DOCTYPE html>
<html>
<head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>
        Sign In - Webex
</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script>
    window.jQuery || document.write("<script src='/idb/js/jquery-3.5.1.min.js'><\/script>");
</script>
<link rel="stylesheet" href="/idb/css/momentum-ui_fbdee616043ab213856f370993c83f01.min.css"/>
<link rel="stylesheet" href="/idb/css/idbstyle_service_default.css" type="text/css" />
<script src="/idb/js/auth_symphony_997017a549f50f21347311e1488607ab.js"></script>
        <link rel="stylesheet" href="/idb/css/idbstyle_symphony_a2736f93e46b8c14f389ccac12436dcb.css" type="text/css" />

<link rel="apple-touch-icon" sizes="180x180" href="/idb/favicons/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/idb/favicons/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/idb/favicons/favicon-16x16.png" />
<link rel="manifest" href="/idb/favicons/manifest.json" />
<link rel="mask-icon" href="/idb/favicons/safari-pinned-tab.svg" color="#07C1E4" />
<link rel="shortcut icon" href="/idb/favicons/favicon.ico" />
<meta name="msapplication-config" content="/idb/favicons/browserconfig.xml" />
<meta name="theme-color" content="#ffffff" />
<meta name="robots" content="noindex, nofollow" />
        <!-- Ref: http://seclab.stanford.edu/websec/framebusting/framebust.pdf -->
<style id="antiClickjack">body{display:none !important;}</style>
<noscript><style>body{display:block !important;}</style></noscript>
<script type="text/javascript">
    if (self === top) {
        var antiClickjack = document.getElementById("antiClickjack");
        antiClickjack.parentNode.removeChild(antiClickjack);
    } else {
        top.location = self.location;
    }
</script>
<script>
        var nameValidated = false;
        var redirectUrl = "https://idbroker.webex.com/idb/IdBGlobalLogin?type=login&goto=https%3A%2F%2Fidbroker.webex.com%2Fidb%2Foauth2%2Fv1%2Fauthorize%3Fclient_id%3DC7aa20b0a57cae4127d1e08b15e3a94efacd5c7bb3e1a70ceed4308903a5b807b%26response_type%3Dcode%26redirect_uri%3Dhttps%253A%252F%252Fwww.your-oauth-website-here.dk%252Foauth%26scope%3Dspark%253Aall%2520spark%253Akms%26state%3Dset_state_here";
        $(document).ready(function() {
                $("#md-form").submit(function(e){
                        e.preventDefault();
                        if(nameValidated) {
                                processForm();
                        }
                });
                var cookieEmail = "";
                if(cookieEmail.length > 0) {
                        $('#GlobalEmailLookupForm').find('input[id="email"]').val(cookieEmail);
                        $('#GlobalEmailLookupForm').find('input[id="isCookie"]').val("true");
                        $('#GlobalEmailLookupForm').submit();
                }
        });
        function validateName(name, nameId) {
        nameId = nameId.replace('IDToken' ,'');
        var divId = 'DivToken' + nameId;
        if(name.length > 0) {
                $.ajax({
                        type: "POST",
                        url: "/idb/validateEmail",
                        data: { user: name, action: 'login', validate: "true" }
                })
                .done(function( responseData ) {
                        if(responseData.status == 'invalid') {
                                document.getElementById('nameContextualError'+nameId).innerHTML = "Enter a valid email address. Example: name@email.com"
                                highlightErrorInputTextbox(divId);
                        } else {
                                nameValidated = true;
                        }
                });
        }
    }
        function processForm() {
                var email = $.trim(document.getElementById('IDToken1').value);
                if(nameValidated) {
                        $('#GlobalEmailLookupForm').find('input[id="email"]').val(email);
                        $('#GlobalEmailLookupForm').submit();
                } else {
                        if(email.length > 0) {
                        $.ajax({
                                type: "POST",
                                url: "/idb/validateEmail",
                                data: { user: email, action: 'login', validate: "true" }
                        })
                        .done(function( responseData ) {
                                if(responseData.status == 'invalid') {
                                        document.getElementById('nameContextualError1').innerHTML = "Enter a valid email address. Example: name@email.com"
                                        highlightErrorInputTextbox('DivToken1');
                                } else {
                                        $('#GlobalEmailLookupForm').find('input[id="email"]').val(email);
                                        $('#GlobalEmailLookupForm').submit();
                                }
                        });
                }
                }
                return false;
        }
</script>
        <style>
                @media (forced-colors: active) {
                        .md-button--blue {
                                border: 1px solid;
                        }
                }
        </style>
</head>
<body id="login" class="md md--sites">
        <div id="globalInfo" style="display:none;">
                <div>
                        It appears that cookies are not enabled on your computer, so some functions will not work. To enable cookies, change the privacy settings in your browser, and then refresh the page.
                </div>
                <a id="close_crossplatform_message" href="javascript:">
                        Close
                </a>
        </div>
        <noscript>
                <div>
                        It appears that JavaScript is not enabled on your computer, so some functions will not work. To enable JavaScript, change the privacy settings in your browser, and then refresh the page.
                </div>
        </noscript>
        <div class="md-panel md-panel--form md-panel--full">
                <div class="md-panel__main">
            <div class="md-panel__image ci__logo"></div>
                        <div class="md-panel__title">
                Enter your email address
            </div>
                        <form class="md-panel__form" id="md-form" novalidate="">
                <div class="md-input-container md-input--filled" id="DivToken1">
                                        <div class="md-input__wrapper">
                                                <input class="md-input" id="IDToken1" data-monitor-id="IDToken1"
                                                        name="IDToken1" value="" autocomplete="email"
                                                        placeholder="Email address"
                                                        alt="Email address"
                                                        onblur="validateName($.trim(this.value), this.id);" maxlength="512"
                                                        type="email" autofocus>
                                        </div>
                    <div class="md-input__messages" id="DivErrorToken1">
                        <div class="message" id="nameContextualError1">
                            Enter the email address for your Webex account.
                        </div>
                    </div>
                </div>
                <div class="md-panel__cta">
                    <button name="btnOK" type="submit" id="IDButton2"
                            class="md-button md-button--blue" onClick="processForm();">
                        Next
                    </button>
                </div>
                        </form>
                </div>
                <form name="GlobalEmailLookup" id="GlobalEmailLookupForm" method="post" action="/idb/globalLogin">
                        <input type="hidden" id="email" name="email" value="" />
                        <input type="hidden" id="isCookie" name="isCookie" value="false" />
                        <input type="hidden" id="ForceAuth" name="ForceAuth" value="false" />
                        <input type="hidden" id="cisService" name="cisService" value="common" />
                                <input type="hidden" name="gotoUrl" value="aHR0cHM6Ly9pZGJyb2tlci53ZWJleC5jb20vaWRiL29hdXRoMi92MS9hdXRob3JpemU/Y2xpZW50X2lkPUM3YWEyMGIwYTU3Y2FlNDEyN2QxZTA4YjE1ZTNhOTRlZmFjZDVjN2JiM2UxYTcwY2VlZDQzMDg5MDNhNWI4MDdiJnJlc3BvbnNlX3R5cGU9Y29kZSZyZWRpcmVjdF91cmk9aHR0cHMlM0ElMkYlMkZ3d3cueW91ci1vYXV0aC13ZWJzaXRlLWhlcmUuZGslMkZvYXV0aCZzY29wZT1zcGFyayUzQWFsbCUyMHNwYXJrJTNBa21zJnN0YXRlPXNldF9zdGF0ZV9oZXJl" />
                        <input type="hidden" id="encodedParamsString" name="encodedParamsString" value="dHlwZT1sb2dpbiY=" />
                </form>
<div id="footer" class="md-panel__footer">
    <img class="footer__logo" src="/idb/images/cisco-webex/lockup/cisco-webex-lockup-blue.svg" alt="Cisco Webex logo"/>
    <div id="footer-links" class="footer__copyright">
        By using Webex you accept the
            <a href="https://www.cisco.com/c/en/us/about/legal/cloud-and-software/cloud-terms.html" target="_blank" rel="noopener">
                Terms of Service
            </a> &
            <a href="https://www.cisco.com/web/siteassets/legal/privacy.html" target="_blank" rel="noopener">
                Privacy Statement
            </a>.
            <a href="https://www.webex.com" target="_blank" rel="noopener">
                Learn more about
            </a> Webex
    </div>
</div>
        </div>
</body>
</html>

我只是得到登录屏幕。

或者:是否可以使用 Python CLI 登录 WebEx 网站?

如果我可以登录 Cisco WebEx 开发人员站点,然后使用此会话获取新代码,那可能会成功。

更新:我已经设法通过“输入电子邮件地址”,但我现在卡在输入密码上,但我继续研究如何登录 WebEx 网站。

with requests.Session() as s:
    login_url = "https://developer.webex.com/login"
    result = s.get(login_url)
    payload = { "email": "xx@xx.xx" }
    print(result.url)
    result = s.post(result.url, data=payload)
    print(result.text)

对此事的任何想法将不胜感激。

谢谢你。

4

1 回答 1

2

原来我没有正确阅读文档,对任何花时间阅读/等的人感到抱歉。

刷新普通令牌时,刷新令牌到期也将重置。我不知道是这种情况,但在今天联系思科开发支持后,他们向我展示了。

官方回复是:

你好,

感谢您联系 Webex 开发人员支持。没有办法完全自动化 OAuth 授权流程,作为第一个手动步骤,用户授权集成代表他们行事始终是强制性的。但是,一旦访问令牌过期甚至在此之前,您可以使用刷新令牌来延长访问令牌的有效期。这样,刷新令牌的有效性也将被更新,因此您实际上可以无限期地刷新您的访问令牌。出于性能原因,刷新令牌到期时间每天最多重置一次,因此计数器似乎会在一天内倒计时,但如果您要在第二天刷新它,您应该会看到该时间/整数回去吧。

我用来刷新令牌的代码:

def refreshCiscoWebExToken(refresh_token):
    """Refresh access token"""
    payload = ( "grant_type=refresh_token&client_id={0}&client_secret={1}&"
                "refresh_token={2}").format(clientID, secretID, refresh_token)
    response = requests.post(url=TokenUrl, data=payload, headers=TokenHeaders)
    if response.status_code == 200:
        results = json.loads(response.text)
        access_token = results["access_token"]
        expires_in = results["expires_in"]
        return(access_token, expires_in)

我希望这可以/将帮助其他人寻找答案。

于 2020-12-17T09:53:05.923 回答