我有点陷阱,我需要在同一段代码(C#)中从相同的服务主体访问Azure Event Hub和Azure Data Lake。服务主体是Azure AD应用程序,我正在使用证书进行身份验证。
如果我使用ADAL 2.x并进行身份验证,我可以很好地连接到Azure Data Lake,但事件中心(WindowsAzure.ServiceBus)无法进行身份验证(请参阅下面的内容)。
我用于为Azure Data Lake创建凭据的ADAL 2.x代码如下所示,这可以100%正常工作:
public static ServiceClientCredentials GetCreds_SPI_Cert(string tenant, Uri tokenAudience, string clientId, string certificateThumbprint)
{
var certificate = FindCertificateByThumbprint(certificateThumbprint);
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
var clientAssertionCertificate = new ClientAssertionCertificate(clientId, certificate);
var serviceSettings = ActiveDirectoryServiceSettings.Azure;
serviceSettings.TokenAudience = tokenAudience;
var creds = ApplicationTokenProvider.LoginSilentWithCertificateAsync(tenant, clientAssertionCertificate, serviceSettings).GetAwaiter().GetResult();
return creds;
}
如果我升级到ADAL v3以获得访问事件中心(WindowsAzure.ServiceBus需要它),那么以下代码可以正常工作(对于事件中心):
public static TokenProvider GetTokenProviderViaCetificate(string tenant, Uri tokenAudience, string clientId, string certificateThumbprint)
{
var certificate = FindCertificateByThumbprint(certificateThumbprint);
return TokenProvider.CreateAadTokenProvider(
new AuthenticationContext($"https://login.windows.net/{tenant}"),
new ClientAssertionCertificate(clientId, certificate),
ServiceAudience.EventHubsAudience);
}
请注意,Event Hub身份验证CreateAadTokenProvider
中的令牌提供程序仅在ADALv3中可用。 Service Bus和Data Lake客户端也需要不同类型的凭证。
如果我使用ADAL V3并返回到Data Lake代码,则GetCreds_SPI_Cert
会因以下错误而失败:
找不到方法:'System.Threading.Tasks.Task`1 Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.AcquireTokenAsync(System.String,Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate)'。
简而言之,如何使用ADAL v3对Azure Data Lake的Azure AD App服务主体进行身份验证(使用证书)?由于事件中心依赖性,我无法降级到ADAL 2.x.
可能有助于设计解决方案的东西,尽管可能不是直接解决方案,是github repo深层记录的身份验证适配器:
由于混合了旧的SDK *和新的SDK *,可能会发生身份验证冲突。依赖于新身份验证库(Microsoft.Rest.ClientRuntime.Azure.Authentication,type = ServiceClientCredentials)创建的凭据类型的SDK与旧SDK中使用的凭据类型(Microsoft.Azure.Common,type = SubscriptionCloudCredentials)不兼容。问题是使用两个不同的身份验证库需要您进行两次身份验证,这是一种痛苦的经历。
public class SubscriptionCredentialsAdapter : SubscriptionCloudCredentials
{
ServiceClientCredentials _credentials;
string _subscriptionId;
public SubscriptionCredentialsAdapter(ServiceClientCredentials wrapped, string subscriptionId)
{
_credentials = wrapped;
_subscriptionId = subscriptionId;
}
public override string SubscriptionId
{
get { return _subscriptionId; }
}
public override Task ProcessHttpRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return _credentials.ProcessHttpRequestAsync(request, cancellationToken);
}
}