【Azure Developer】Python – Get Access Token by Azure Identity in China Azure Environment - LuBu0505/My-Code GitHub Wiki

问题描述

使用Azure Identity,根据指定的客户端凭据获取Access Token中,先后遇见了

  • “ValueError: "get_token" requires at least one scope”
  • “ClientSecretCredential.get_token failed: Authentication failed: sequence item 0: expected str instance, list found”

最初的Python 代码如下:

from azure.identity import ClientSecretCredential,AzureAuthorityHosts 
from azure.mgmt.resource import SubscriptionClient 
# Service principal credentials for Azure 

credential = ClientSecretCredential(tenant_id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", client_id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", client_secret="xxxxxxxxxxxx.xxxx")

access_token = credential.get_token(scopes=["https://management.chinacloudapi.cn/.default"]) 

print(access_token)

问题解答

第一个问题: get_token 的至少需要一个 scope参数

image.png

以上代码按照python常规的方式,为传递的参数指定参数名,根据ClientSecretCredential get_token方法介绍,参数名就是 scopes 。 image.png

在没有想明白的情况下,最后去掉了指定参数名,直接传入值。问题一消失,问题二产生。 image.png

第二个问题:get_token方法失败,参数传递序列中,第一个参数期待的是一个str,但是发现是一个list。

ClientSecretCredential.get_token failed: Authentication failed: sequence item 0: expected str instance, list found

这里是一个copy错误,scopes参数从其它代码中复制过来。并没有仔细对比这里的get_token需要传递的不是数组([]), 而是一个字符串(str)。把第一个参数修改为字符串后。成功获取到Access Token。

正确的完整Python 代码

from azure.identity import ClientSecretCredential,AzureAuthorityHosts 
from azure.mgmt.resource import SubscriptionClient 

# Service principal credentials for Azure

credential = ClientSecretCredential(tenant_id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", client_id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", client_secret="xxxxxxxxxxxx.xxxx")

access_token = credential.get_token("https://management.chinacloudapi.cn/.default") 
print(access_token)

附录:理解target=" ".join(target)

|

错误消息:

…\site-packages\msal\token_cache.py", line 103, in _get_access_token

    target=" ".join(target),

TypeError: sequence item 0: expected str instance, list found

| |

源代码:

… …

        return self._get(

            self.CredentialType.ACCESS_TOKEN,

            self.key_makers[TokenCache.CredentialType.ACCESS_TOKEN](

                home_account_id=home_account_id,

                environment=environment,

                client_id=client_id,

                realm=realm,

                target=" ".join(target),

                ),

            default=default)

| |

测试:

print(" ".join(["Hello","World",", This is join method test." ]))

输出:

Hello World , This is join method test.

|

说明:

在Python中," ".join(target)这段代码的作用是将target序列中的元素通过指定的分隔符(这里是空格)连接成一个新的字符串。

例如,如果target是['Hello', 'World'],那么" ".join(target)的结果将是'Hello World'。

这个方法通常用于将多个字符串片段合并成一个完整的字符串。

[END]

当在复杂的环境中面临问题,格物之道需:浊而静之徐清,安以动之徐生。 云中,恰是如此!