ADAL获取的Token调用Azure区块链工作台API报401的原因及解决方法
解决Azure Blockchain Workbench API调用的401未授权问题
我帮你排查下这个401错误的核心原因:你用ADAL请求令牌时指定的资源(resource)不对。手动从网站获取的令牌是针对Blockchain Workbench API生成的,但代码里你把资源设成了https://graph.windows.net(微软Graph API的资源标识符),导致生成的令牌受众(aud字段)和Blockchain Workbench API的要求不匹配,自然会被拒绝授权。
步骤1:获取Blockchain Workbench API的正确资源标识符
你需要先拿到API对应的资源值,有两种简单方法:
- 方法A:解析手动获取的有效令牌
把你从浏览器拿到的Bearer令牌复制到jwt.ms(本地解码工具,无需联网),查看aud字段的值,这个就是API的资源标识符,比如可能是https://votemaadi-4bm4ew.azurewebsites.net或者对应的应用ID URI。 - 方法B:从Azure门户查询
登录Azure门户,找到你的Blockchain Workbench对应的应用注册,在"概述"页面查看"应用ID URI",这个值就是需要的资源。
步骤2:修改Python代码中的资源参数
把代码里的resource参数替换成上面查到的正确值,而不是https://graph.windows.net。修改后的代码示例:
import adal import swagger_client from swagger_client.api_client import ApiClient # 替换为你查到的Blockchain Workbench API资源标识符 target_resource = "https://votemaadi-4bm4ew.azurewebsites.net" context = adal.AuthenticationContext("https://login.microsoftonline.com/kumarshobhit98outlook.onmicrosoft.com/", api_version=None) client_id = "c62087b9-cfed-4105-a9c2-4fd3953ceed5" username = "shobhit@kumarshobhit98outlook.onmicrosoft.com" password = "pass" token = context.acquire_token_with_username_password( resource=target_resource, username=username, password=password, client_id=client_id ) print(token['accessToken'])
步骤3:验证令牌并调用API
获取新令牌后,再用jwt.ms解码确认aud字段和Blockchain Workbench API的受众一致,然后带着这个令牌调用API,就能正常通过授权了。
额外建议:考虑迁移到MSAL
ADAL已经处于维护模式,微软官方推荐使用MSAL(Microsoft Authentication Library)来处理Azure AD认证,MSAL的API更简洁且支持更多场景。如果后续需要升级,MSAL的代码示例大概是这样:
from msal import PublicClientApplication client_id = "c62087b9-cfed-4105-a9c2-4fd3953ceed5" authority = "https://login.microsoftonline.com/kumarshobhit98outlook.onmicrosoft.com/" target_resource = "https://votemaadi-4bm4ew.azurewebsites.net" app = PublicClientApplication(client_id, authority=authority) result = app.acquire_token_by_username_password( username="shobhit@kumarshobhit98outlook.onmicrosoft.com", password="pass", scopes=[f"{target_resource}/.default"] ) if "access_token" in result: print(result["access_token"]) else: print(result.get("error"), result.get("error_description"))
内容的提问来源于stack exchange,提问作者Shobhit Kumar
相关产品推荐
相关产品推荐

