python - 授权标头未确认为所需格式 - Python Cosmos-db api
问题描述
我正在使用 python cosmos-db 库来:创建数据库、容器和用户。
azure cosmos 实例正在本地运行。
使用主密钥,我可以成功创建数据库、容器和用户。
但是,一旦我有了一个用户并生成了令牌,当我尝试查询数据库时,我就会收到以下错误:
授权标头未确认为所需的格式。请验证并重试。
我曾尝试从 Microsoft 执行整个示例代码,但它会引发相同的错误。示例代码可以在这里找到:https ://github.com/Azure/azure-sdk-for-python/blob/4f96d8a8dfde9b4cac9d2103b5f58d5705b26ded/sdk/cosmos/azure-cosmos/samples/access_cosmos_with_resource_token.py
这是用于打开令牌客户端和查询集合的代码片段。
def run_sample():
client = cosmos_client.CosmosClient(HOST, {"masterKey": MASTER_KEY})
#</configureConnectivity>
try:
try:
db = client.create_database(DATABASE_ID)
except exceptions.CosmosResourceExistsError:
db = client.get_database_client(DATABASE_ID)
try:
container = db.create_container(
id=CONTAINER_ID, partition_key=PARTITION_KEY
)
except exceptions.CosmosResourceExistsError:
container = db.get_container_client(CONTAINER_ID)
user = create_user_if_not_exists(db, USERNAME)
# Permission to perform operations on all items inside a container
permission_definition = {
"id": CONTAINER_ALL_PERMISSION,
"permissionMode": documents.PermissionMode.All,
"resource": container.container_link,
}
permission = create_permission_if_not_exists(user, permission_definition)
token = {}
token[container.id] = permission.properties["_token"]
# Use token to connect to database
token_client = cosmos_client.CosmosClient(HOST, token)
token_db = token_client.get_database_client(DATABASE_ID)
token_container = token_db.get_container_client(CONTAINER_ID)
# Query for items in a certain partition
token_client_query(token_container, USERNAME_2)
def token_client_query(container, username):
try:
for item in container.query_items(
query="SELECT * FROM my_container c WHERE c.username=@username",
parameters=[{"name": "@username", "value": username}],
partition_key=username,
):
print(json.dumps(item, indent=True))
except exceptions.CosmosHttpResponseError:
print("Error in querying item(s)")
由此,我收到 401 响应。关于如何解决这个问题的任何想法?
解决方案
如上述评论所述,问题在于令牌的格式。
授权字符串应该在添加到 REST 请求之前进行编码,以确保它不包含无效字符。确保它是使用 MIME RFC2045 进行 Base64 编码的。
Azure Cosmos DB SQL API 中的访问控制
由此,我使用 urllib 库对令牌进行编码并将其传递给解决了问题的 http 请求,因为响应是所需的文档。
import urllib.parse
urllib.parse.quote_plus(token[container.id])