问题描述
使用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参数
以上代码按照python常规的方式,为传递的参数指定参数名,根据ClientSecretCredential get_token方法介绍,参数名就是 scopes 。
在没有想明白的情况下,最后去掉了指定参数名,直接传入值。问题一消失,问题二产生。
第二个问题: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]