Проблема с производительностью для управляемой идентификации для проверки подлинности SQL через приложение-функцию Azure
Приведенный ниже код работает нормально, но вызывает проблемы с производительностью, поскольку для каждого запроса требуется в среднем на 3 секунды больше. Что может быть для этого другим подходом?
public QuoteContext(DbContextOptions options) : base(options)
{
var conn = (Microsoft.Data.SqlClient.SqlConnection)Database.GetDbConnection();
var credential = new DefaultAzureCredential();
var token = credential
.GetToken(new Azure.Core.TokenRequestContext(
new[] { "https://database.windows.net/.default" }));
conn.AccessToken = token.Token;
}
1 ответ
Спасибо, Thomas и J Weezy Разместите свое предложение в качестве ответа, чтобы помочь другим членам сообщества.
"Примечание. Вам необходимо перенести секрет в KeyVault. В данном случае мы назвали его
AzureSqlSecret
. Это необходимо для получения учетных данных пользователя базы данных.
Конструктор класса Entities, который вызывает
AzureAuthenticationInterceptor
как следует:
public ProjectNameEntities() :
base(new DbContextOptionsBuilder<ProjectNameEntities>()
.UseSqlServer(ConfigurationManager.ConnectionStrings["ProjectNameEntities"].ConnectionString)
.AddInterceptors(new AzureAuthenticationInterceptor())
.Options)
{ }
AzureAuthenticationInterceptor:
#region NameSpaces
using Azure.Core;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Configuration;
using System.Data.Common;
using System.Threading;
using System.Threading.Tasks;
#endregion
namespace <ProjectName>.DataAccess.Helpers
{
public class AzureAuthenticationInterceptor : DbConnectionInterceptor
{
#region Constructor
public AzureAuthenticationInterceptor()
{
SecretClientOptions objSecretClientOptions;
string strAzureKeyVaultResourceIdentifier;
string strAzureKeyVault;
string strAzureKeyVaultUri;
strAzureKeyVaultResourceIdentifier = ConfigurationManager.AppSettings["Azure:ResourceIdentifiers:KeyVault"];
strAzureKeyVault = ConfigurationManager.AppSettings["Azure:KeyVaults:TaxPaymentSystem"];
strAzureKeyVaultUri = strAzureKeyVaultResourceIdentifier.Replace("{0}", strAzureKeyVault);
// Set the options on the SecretClient. These are default values that are recommended by Microsoft.
objSecretClientOptions = new SecretClientOptions()
{
Retry =
{
Delay= TimeSpan.FromSeconds(2),
MaxDelay = TimeSpan.FromSeconds(16),
MaxRetries = 5,
Mode = RetryMode.Exponential
}
};
this.SecretClient = new SecretClient(
vaultUri: new Uri(strAzureKeyVaultUri),
credential: new DefaultAzureCredential(),
objSecretClientOptions
);
this.KeyVaultSecret = this.SecretClient.GetSecret("AzureSqlSecret");
this.strKeyVaultSecret = this.KeyVaultSecret.Value;
this.strAzureResourceIdentifierAuthentication = ConfigurationManager.AppSettings["Azure:ResourceIdentifiers:Authentication"];
this.strAzureResourceIdentifierDatabase = ConfigurationManager.AppSettings["Azure:ResourceIdentifiers:DataBase"];
this.strClientId = ConfigurationManager.AppSettings["Azure:DatabaseUsername:ClientId"];
this.strTenantId = ConfigurationManager.AppSettings["Azure:TenantId"];
}
#endregion
#region Methods
public override async ValueTask<InterceptionResult> ConnectionOpeningAsync(
DbConnection objDbConnection,
ConnectionEventData objEventData,
InterceptionResult objReturn,
CancellationToken objCancellationToken = default)
{
_ILogger.Debug("Reached the Async Interceptor method");
if (objDbConnection is SqlConnection objSqlConnection)
{
objSqlConnection.AccessToken = GetAccessToken();
}
return objReturn;
}
public override InterceptionResult ConnectionOpening(
DbConnection objDbConnection,
ConnectionEventData objConnectionEventData,
InterceptionResult objReturn)
{
_ILogger.Debug("Reached the non-Async Interceptor method");
if (objDbConnection is SqlConnection objSqlConnection)
{
objSqlConnection.AccessToken = GetAccessToken();
}
return objReturn;
}
private string GetAccessToken()
{
AuthenticationContext objAuthenticationContext;
AuthenticationResult objAuthenticationResult;
ClientCredential objClientCredential;
objAuthenticationContext = new AuthenticationContext(string.Format("{0}/{1}"
, this.strAzureResourceIdentifierAuthentication
, this.strTenantId));
objClientCredential = new ClientCredential(this.strClientId, this.strKeyVaultSecret);
objAuthenticationResult = objAuthenticationContext.AcquireTokenAsync(this.strAzureResourceIdentifierDatabase, objClientCredential).Result;
return objAuthenticationResult.AccessToken;
}
#endregion
#region Properties
readonly <ProjectName>.Common.Logging.ILogger _ILogger = <ProjectName>.Common.Logging.LogWrapper.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private SecretClient SecretClient;
private KeyVaultSecret KeyVaultSecret;
private string strAzureResourceIdentifierDatabase;
private string strAzureResourceIdentifierAuthentication;
private string strKeyVaultSecret;
private string strClientId;
private string strTenantId;
#endregion
}
}