- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试将我的 C# 控制台应用程序 (.net core 2.1) 连接到 blob 存储。我通过几种不同的方式初始化 Blob 存储客户端。他们是:
在我的代码中,如果未显式设置连接字符串,我会根据定义的应用程序设置使用服务原则或 MSI 生成它(下面的示例初始化代码)。无论我使用这三种方式中的哪一种,我最终都会使用连接字符串初始化客户端(在 1. 的情况下显式设置,或者在 2. 和 3. 的情况下使用我的代码生成)。
下面的代码对于 1(连接字符串)和 2(服务原理)100% 正常工作,但在尝试实现 3 (MSI) 时出现错误。
在本地运行时出现此错误:
The access token is from the wrong issuer 'https://sts.windows.net/f8cdef31-a31e-4b4a-93e4-5f571e91255a/'. It must match the tenant 'https://sts.windows.net/{my-subscription-id}/' associated with this subscription. Please use the authority (URL) 'https://login.windows.net/{my-subscription-id}' to get the token. Note, if the subscription is transferred to another tenant there is no impact to the services, but information about new tenant could take time to propagate (up to an hour). If you just transferred your subscription and see this error message, please try back later.
这样,我不知道“f8cdef31-a31e-4b4a-93e4-5f571e91255a”来自哪里,它可能是全局 Microsoft 实例。我尝试通过在启用了 MSI 的 Azure 中的 Webjob 中运行我的代码来缓解此问题,以查看是否有效,我得到:
System.AggregateException: One or more errors occurred. (An exception occurred during service connection, see inner exception for more detail) ---> System.Exception: An exception occurred during service connection, see inner exception for more detail ---> Microsoft.Rest.Azure.CloudException: The client '{my-subscription-id}' with object id '{my-subscription-id}' does not have authorization to perform action 'Microsoft.Storage/storageAccounts/read' over scope '/subscriptions/{my-subscription-id}'.
(注意我已将 MSI 帐户设置为 Blob 存储的“所有者”和“存储帐户 key 运算符(operator)”)
我通过以下方式初始化 CloudStorageAccount 客户端:
public void InitializeClient()
{
// Always using the connection string, no matter how it's generated.
if (ConnectionString.IsNullOrEmpty()) // if not already set, then build.
ConnectionString = BuildStorageConnection().GetAwaiter().GetResult();
CloudStorageAccount.TryParse(ConnectionString, out var storageAccount);
if (storageAccount == null)
throw new InvalidOperationException("Cannot find storage account");
// CloudBlobClient that represents the Blob storage endpoint.
_cloudBlobClient = storageAccount.CreateCloudBlobClient();
}
并按如下方式构建连接字符串:
internal async Task<string> BuildStorageConnection()
{
try
{
string token = null;
if (Config.UseMsi)
{
// Managed Service Identity (MSI) authentication.
var provider = new AzureServiceTokenProvider();
token = provider.GetAccessTokenAsync("https://management.azure.com/").GetAwaiter().GetResult();
if (string.IsNullOrEmpty(token))
throw new InvalidOperationException("Could not authenticate using Managed Service Identity");
_expiryTime = DateTime.Now.AddDays(1);
}
else
{
// Service Principle authentication
// Grab an authentication token from Azure.
var context = new AuthenticationContext("https://login.windows.net/" + Config.TenantId);
var credential = new ClientCredential(Config.AppId, Config.AppSecret);
var tokenResult = context.AcquireTokenAsync("https://management.azure.com/", credential).GetAwaiter().GetResult();
if (tokenResult == null || tokenResult.AccessToken == null)
throw new InvalidOperationException($"Could not authenticate using Service Principle");
_expiryTime = tokenResult.ExpiresOn;
token = tokenResult.AccessToken;
}
// Set credentials and grab the authenticated REST client.
var tokenCredentials = new TokenCredentials(token);
var client = RestClient.Configure()
.WithEnvironment(AzureEnvironment.AzureGlobalCloud)
.WithLogLevel(HttpLoggingDelegatingHandler.Level.BodyAndHeaders)
.WithCredentials(new AzureCredentials(tokenCredentials, tokenCredentials, string.Empty, AzureEnvironment.AzureGlobalCloud))
.WithRetryPolicy(new RetryPolicy(new HttpStatusCodeErrorDetectionStrategy(), new FixedIntervalRetryStrategy(3, TimeSpan.FromMilliseconds(500))))
.Build();
// Authenticate against the management layer.
var azureManagement = Azure.Authenticate(client, string.Empty).WithSubscription(Config.SubscriptionId);
// Get the storage namespace for the passed in instance name.
var storageNamespace = azureManagement.StorageAccounts.List().FirstOrDefault(n => n.Name == Config.StorageInstanceName);
// If we cant find that name, throw an exception.
if (storageNamespace == null)
{
throw new InvalidOperationException($"Could not find the storage instance {Config.StorageInstanceName} in the subscription with ID {Config.SubscriptionId}");
}
// Storage accounts use access keys - this will be used to build a connection string.
var accessKeys = await storageNamespace.GetKeysAsync();
// If the access keys are not found (not configured for some reason), throw an exception.
if (accessKeys == null)
{
throw new InvalidOperationException($"Could not find access keys for the storage instance {Config.StorageInstanceName}");
}
// We just default to the first key.
var key = accessKeys[0].Value;
// Build and return the connection string.
return $"DefaultEndpointsProtocol=https;AccountName={Config.StorageInstanceName};AccountKey={key};EndpointSuffix=core.windows.net";
}
catch (Exception e)
{
Logger?.LogError(e, "An exception occured during connection to blob storage");
throw new Exception("An exception occurred during service connection, see inner exception for more detail", e);
}
}
我获取访问 token 的主要区别在于,使用服务原则我有身份验证上下文,而使用 MSI 我没有。这会影响身份验证的范围吗?非常感谢任何帮助和建议!
最佳答案
刚刚意识到如何解决上述问题 - 更改 GetTokenAsync 以使用 TenantId 的第二个参数为身份验证调用提供上下文。
这是您需要的代码:
token = await provider.GetAccessTokenAsync("https://management.azure.com/", Config.TenantId);
关于c# - 使用 MSI 向 Azure Blob 存储进行身份验证时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53639305/
我的应用程序从一个有 5 个选项卡的选项卡栏 Controller 开始。一开始,第一个出现了它的名字,但其他四个没有名字,直到我点击它们。然后根据用户使用的语言显示名称。如何在选项卡栏出现之前设置选
我有嵌套数组 json 对象(第 1 层、第 2 层和第 3 层)。我的问题是数据表没有出现。任何相关的 CDN 均已导入。该表仅显示部分。我引用了很多网站,但都没有解决我的问题。 之前我使用标准表来
我正在尝试设置要显示的 Parse PFLoginViewController。这是我的一个 View Controller 的类。 import UIKit import Parse import
我遇到了这个问题,我绘制的对象没有出现在 GUI 中。我知道它正在被处理,因为数据被推送到日志文件。但是,图形没有出现。 这是我的一些代码: public static void main(Strin
我有一个树状图,其中包含出现这样的词...... TreeMap occurrence = new TreeMap (); 字符串 = 单词 整数 = 出现次数。 我如何获得最大出现次数 - 整数,
因此,我提示用户输入变量。如果变量小于 0 且大于 10。如果用户输入 10,我想要求用户再次输入数字。我问时间的时候输入4,它说你输入错误。但在第二次尝试时效果很好。例如:如果我输入 25,它会打印
我已经用 css overflow 属性做了一个例子。在这个例子中我遇到了一个溢出滚动的问题。滚动条出现了,但没有工作意味着每当将光标移动到滚动条时,在这个滚动条不活动的时间。我对此一无所知,所以请帮
我现在正在做一个元素。当您单击一个元素时,会出现以下信息,我想知道如何在您单击下一个元素而不重新单击同一元素时使其消失....例如,我的元素中有披萨,我想单击肉披萨看到浇头然后点击奶酪披萨看到浇头和肉
我有一个路由器模块,它将主题与正则表达式进行比较,并将出现的事件与一致的键掩码链接起来。 (它是一个简单的 url 路由过滤,如 symfony http://symfony.com/doc/curr
这个问题在这里已经有了答案: 9年前关闭。 Possible Duplicate: mysql_fetch_array() expects parameter 1 to be resource, bo
我在底部有一个带有工具栏的 View ,我正在使用 NavigationLink 导航到该 View 。但是当 View 出现时,工具栏显示得有点太低了。大约半秒钟后,它突然跳到位。它只会在应用程序启
我试图在我的应用程序上为背景音乐添加一个 AVAudioPlayer,我正在主屏幕上启动播放器,尝试在应用程序打开时开始播放但出现意外行为... 它播放并立即不断创建新玩家并播放这些玩家,因此同时播放
这是获取一个数字,获取其阶乘并将其加倍,但是由于基本情况,如果您输入 0,它会给出 2 作为答案,因此为了绕过它,我使用了 if 语句,但收到错误输入“if”时解析错误。如果你们能提供帮助,我真的很感
暂停期间抛出异常 android.os.DeadObjectException 在 android.os.BinderProxy.transactNative( native 方法) 在 androi
我已经为猜词游戏编写了一些代码。它从用户输入中读取字符并在单词中搜索该字符;根据字符是否在单词中,程序返回并控制一些变量。 代码如下: import java.util.Random; import
我是自动化领域的新手。这是我的简单 TestNG 登录代码,当我以 TestNG 身份运行该代码时,它会出现 java.lang.NullPointerException,双击它会突出显示我导航到 U
我是c#程序员,我习惯了c#的封装语法和其他东西。但是现在,由于某些原因,我应该用java写一些东西,我现在正在练习java一天!我要创建一个为我自己创建一个虚拟项目,以便让自己更熟悉 Java 的
我正在使用 Intellij,我的源类是 main.com.coding,我的资源文件是 main.com.testing。我将 spring.xml 文件放入资源文件中。 我的测试类位于 test.
我想要我的tests folder separate到我的应用程序代码。我的项目结构是这样的 myproject/ myproject/ myproject.py moduleon
这个问题已经有答案了: What is a NullPointerException, and how do I fix it? (12 个回答) 已关闭 6 年前。 因此,我尝试比较 2 个值,一个
我是一名优秀的程序员,十分优秀!