当前位置: 首页 > 知识库问答 >
问题:

使用Azure active directory进行身份验证时调用Azure管理库API时出错

赵涵亮
2023-03-14

我的公司正在调查关于Azure的报道。我们只希望我们的客户给我们只读凭据供我们使用。我做了一些研究,看起来Azure Active Directory就是这么做的。因此,我希望使用只读Azure Directory应用程序进行身份验证。

为了让我开始,我关注了这个关于通过Azure Active Directory使用管理API的博客。

https://msdn.microsoft.com/en-us/library/azure/dn722415.aspx

    private static string GetAuthorizationHeader()
    {
        AuthenticationResult result = null;

        var context = new AuthenticationContext("https://login.windows.net/" + ConfigurationManager.AppSettings["tenantId"]);

        string clientId = ConfigurationManager.AppSettings["clientId"];
        string clientSecret = ConfigurationManager.AppSettings["clientSecret"];
        ClientCredential clientCred = new ClientCredential(clientId, clientSecret);

        var thread = new Thread(() =>
        {
            result = context.AcquireToken(
              "https://management.core.windows.net/",
              clientCred);
        });

        thread.SetApartmentState(ApartmentState.STA);
        thread.Name = "AquireTokenThread";
        thread.Start();
        thread.Join();

        if (result == null)
        {
            throw new InvalidOperationException("Failed to obtain the JWT token");
        }

        string token = result.AccessToken;
        return token;
    }

我可以得到访问令牌(耶)。但是现在,当我尝试将其与Azure Management library客户机一起使用时,我得到了这个错误:

“ForbiddenError:服务器无法对请求进行身份验证。请验证证书是否有效,是否与此订阅相关联。”

我在我的应用程序中重新检查了我的权限。看起来不错。我试着让所有东西都能完全进入,看看这是否会有所不同。

以下是我的完整代码供参考:

class Program
{
    static void Main(string[] args)
    {
        var token = GetAuthorizationHeader();

        var credential = new TokenCloudCredentials(ConfigurationManager.AppSettings["subscriptionId"], token);

        using (var computeClient = new ComputeManagementClient(credential))
        {
            var images = computeClient.VirtualMachineOSImages.List();
        }
    }

    private static string GetAuthorizationHeader()
    {
        AuthenticationResult result = null;

        var context = new AuthenticationContext("https://login.windows.net/" + ConfigurationManager.AppSettings["tenantId"]);

        string clientId = ConfigurationManager.AppSettings["clientId"];
        string clientSecret = ConfigurationManager.AppSettings["clientSecret"];
        ClientCredential clientCred = new ClientCredential(clientId, clientSecret);

        var thread = new Thread(() =>
        {
            result = context.AcquireToken(
              "https://management.core.windows.net/",
              clientCred);
        });

        thread.SetApartmentState(ApartmentState.STA);
        thread.Name = "AquireTokenThread";
        thread.Start();
        thread.Join();

        if (result == null)
        {
            throw new InvalidOperationException("Failed to obtain the JWT token");
        }

        string token = result.AccessToken;
        return token;
    }
}

编辑:已经取得进展。正如我与Gaurav讨论的那样,我需要放弃Azure管理库,因为到目前为止,它似乎不支持Azure资源管理器(ARM)API!所以我做了原始的web请求。它按预期工作。如果我从我的广告应用程序中删除角色访问,我将被拒绝访问。当我有它的时候,我得到了数据。

我不确定的一件事是如何使它成为我的应用程序自动添加到新资源。

    class Program
{
    static void Main(string[] args)
    {
        var token = GetAuthorizationHeader();

        string subscriptionId = ConfigurationManager.AppSettings["subscriptionId"];
        string resourceGroupName = ConfigurationManager.AppSettings["resourceGroupName"];
        var uriListMachines = string.Format("https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Compute/virtualmachines?api-version=2015-05-01-preview", subscriptionId, resourceGroupName);
        var t = WebRequest.Create(uriListMachines);
        t.ContentType = "application/json";
        t.Headers.Add("Authorization", "Bearer " + token);
        var response = (HttpWebResponse)t.GetResponse();

        string result = "";
        using (var reader = new StreamReader(response.GetResponseStream()))
        {
            result = reader.ReadToEnd(); 
        }

        //Original Attempt:
        //var credential = new TokenCloudCredentials(ConfigurationManager.AppSettings["subscriptionId"], token);

        //using (var client = CloudContext.Clients.CreateComputeManagementClient(credential))
        //{
        //    var images = client.VirtualMachineVMImages.List();
        //}
    }

    private static string GetAuthorizationHeader()
    {
        AuthenticationResult result = null;

        var context = new AuthenticationContext("https://login.windows.net/" + Configurathtml" target="_blank">ionManager.AppSettings["tenantId"]);

        string clientId = ConfigurationManager.AppSettings["clientId"];
        string clientSecret = ConfigurationManager.AppSettings["clientSecret"];
        ClientCredential clientCred = new ClientCredential(clientId, clientSecret);

        var thread = new Thread(() =>
        {
            result = context.AcquireToken(
              "https://management.core.windows.net/",
              clientCred);
        });

        thread.SetApartmentState(ApartmentState.STA);
        thread.Name = "AquireTokenThread";
        thread.Start();
        thread.Join();

        if (result == null)
        {
            throw new InvalidOperationException("Failed to obtain the JWT token");
        }

        string token = result.AccessToken;
        return token;
    }
}

这真是一团糟!但至少我知道现在是怎么回事了。

共有1个答案

阮俊弼
2023-03-14

我相信你是在正确的轨道上为什么你会遇到这个问题。

事情是这样的:

本质上,执行Service Management API的权限是委托的权限,而不是应用程序权限。换句话说,API是在为其获取令牌的用户的上下文中执行的。现在您将获得应用程序的这个令牌(由客户机ID/secret指定)。但是,您的应用程序不能访问您的Azure订阅,因为在您的Azure广告中为此应用程序创建的用户记录类型为Service Principal。由于该服务主体不能访问您的Azure订阅,因此您将得到这个禁止错误(我必须说,该错误是误导性的,因为您根本没有使用证书)。

你可以做以下几件事:

  1. 切换到Azure Resource Manager(ARM)API-ARM API是下一代服务管理API(SM API),而Azure正朝着这个方向发展。它只在Azure广告令牌上工作。如果可能的话,利用它来管理您的Azure资源(尽管您需要记住,到目前为止,并不是所有的Azure资源都可以通过ARM API进行管理)。他们的方法是使用新的Azure Portal将服务主体分配给特定的角色。有关详细信息,请参阅此链接:https://azure.microsoft.com/en-in/documentation/articles/resource-group-create-service-principal-portal/.
  2. 使用X509证书-您可以始终使用基于X509证书的授权来授权您的SM API请求。有关详细信息,请参阅此链接:https://msdn.microsoft.com/en-us/library/azure/ee460782.aspx#bk_cert。这种方法的缺点是,应用程序(或任何有权访问此证书的人)将获得对Azure订阅的完全访问权,并可以在那里执行所有操作(包括删除资源)。
  3. 为用户而不是应用程序获取令牌-这是您可以采用的另一种方法。本质上,要求用户通过控制台应用程序登录到Azure广告,并为该用户获取令牌。同样,请记住,该用户必须是您的Azure订阅中的联合管理员,并且可以完全访问您的Azure订阅,因为在SM API中没有基于角色的访问控制的概念。
 类似资料:
  • 我正在使用以下npm来尝试使用NodeJS创建云服务。https://www.npmjs.com/package/azure-mgmt-compute 这是我正在使用的代码: 我收到错误:“服务器未能对请求进行身份验证。请验证证书是否有效以及是否与此订阅关联”。状态代码403。 我已经完成了这里写的:https://msdn.microsoft.com/en-us/library/azure/gg

  • 我需要一些有关Azure API管理服务的帮助。 目前,我们有一个单页应用程序,它使用Azure上托管的两个后端服务(WebApi.NETCore)。为了对用户进行身份验证和授权,我们使用IdentityServer(也作为服务托管在Azure上)SubscriptionService。在这里,IdSrv对用户进行身份验证,并定义webapp可以访问哪些api。如果用户拥有给定API的权限,Sub

  • 我已经为spring boot应用程序和spring security设置了CRO,如下所示。带有Spring security和jwt令牌的Spring Boot应用程序。 我与其他域一起使用api,所以我在所有控制器上使用交叉源。 所有不需要auth-token(JWT)的api调用在以下配置中都可以正常工作。但是使用所需jwt令牌的api调用失败,错误如下。 我正在尝试添加过滤器,但它没有按

  • 我想通过curl使用Azure AD对Azure服务管理API进行身份验证。 我在默认目录中设置了一个应用程序。在这个免费试用版中,这是我仅有的目录。 当我以oauth令牌endpoint为目标时,我收到一个JWT。 但当我使用该令牌列出我的订阅详细信息时,我收到一个错误: 我已将应用程序的服务管理API的权限授予为“委派权限”,因为“应用程序权限”不可用。 我错过了什么?

  • 我的身份验证系统完全正常工作(我遵循了文档教程)https://symfony.com/doc/current/security/form_login_setup.html). 但我有一个问题:当恶意用户禁用必需的密码字段并尝试登录时,我会收到一个错误500“警告:空密码” 认证系统在一种情况下不起作用: 当用户名与数据库中存储的用户名匹配,但密码为空,并且我尝试登录时,就会出现500 Twig错

  • 问题内容: 我需要使用PostForm方法将代理与auth一起使用。如果我使用类似(简体)的内容: 我可以轻松做到,并且效果很好。但是现在,我正在编辑第三方程序包,并尝试将代理添加到现有代码中: 在我看来,它是行不通的,而且失败了。在此示例中,没有身份验证的代理可以正常工作。有人知道吗,在这种情况下我可以在auth中使用代理吗? 问题答案: 您正在尝试向响应中添加标头,这不是您发送到服务器的内容,