我使用的是 .NET Framework(不是 Core!)4.7.2 并且我正在尝试使用用户分配的托管标识来连接到 Azure SQL Server。托管标识对象已添加到 Azure SQL 服务器上的 db_datareader
、db_datawriter
角色,并且具有连接权限。 (通过我们的 ASP.NET Core 应用独立验证)。
但是,当我们尝试从已在托管标识上启用的 VM 上运行的命令行 .NET Framework 应用程序执行此操作时,它会失败。连接到 Azure SQL 的代码大致如下所示:
// .NET Framework 4.7.2
using(SqlConnection connection = new SqlConnection("Server=tcp:myserver.database.windows.net,1433;Database=MyDb;")){
var credential = new ManagedIdentityCredential(ConfigurationManager.AppSettings["ManagedIdentityId"]);
conn.AccessToken = await credential.GetTokenAsync(
new TokenRequestContext(new[] { "https://database.windows.net/.default" })
);
....
}
它设法很好地抓取了一个令牌(从下面的日志中),但由于这个错误而失败
System.Data.SqlClient.SqlException (0x80131904): Login failed for user ''
我应该检查什么?
(同样的代码在 ASP.NET Core 中也能正常工作)
附录
2021-06-15 14:39:28.7200|INFO|Logger|Received TOKEN - [xxxx real token here xxxx]
2021-06-15 14:39:28.9387|ERROR|Logger|Exception occurred:
System.Data.SqlClient.SqlException (0x80131904): Login failed for user ''.
at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions,
SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance,
SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, DbConnectionPool pool, String accessToken,
Boolean applyTransientFaultHandling, SqlAuthenticationProviderManager sqlAuthProviderManager)
at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey,
Object poolGroupProviderInfo, DbConnectionPool pool,
DbConnection owningConnection, DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject,
DbConnectionOptions options, DbConnectionPoolKey poolKey,
DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout,
Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions,
DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionPool.WaitForPendingOpen()
答案 0 :(得分:1)
根据我的测试,对我来说还可以。我的步骤如下。
配置 Azure AD 身份验证
DROP USER IF EXISTS [the msi name]
GO
CREATE USER [the msi name] FROM EXTERNAL PROVIDER;
GO
ALTER ROLE db_datareader ADD MEMBER [the msi name];
ALTER ROLE db_datawriter ADD MEMBER [the msi name];
GRANT EXECUTE TO [the msi name]
GO
Install-Package Azure.Identity -Version 1.4.0
Install-Package System.Data.SqlClient -Version 4.8.2
static async Task Main(string[] args)
{
string conStr = "Server=tcp:testsql09.database.windows.net,1433;Database=test;";
using (SqlConnection connection = new SqlConnection(conStr))
{
var credential = new ManagedIdentityCredential("ed5f***823");
connection.AccessToken = (await credential.GetTokenAsync(
new TokenRequestContext(new[] { "https://database.windows.net//.default" })
)).Token;
String sql = "SELECT * FROM Blogs";
using (var sqlCommand = new SqlCommand(sql, connection))
{
connection.Open();
using (SqlDataReader reader = sqlCommand.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine("{0} {1}", reader.GetInt32(0), reader.GetString(1));
}
}
}
}
Console.Read();
}