“用户”登录失败。”通过带有EF代码优先实现的MSI访问Azure SQL DB时发生SqlException

时间:2019-01-16 22:39:54

标签: ef-code-first azure-active-directory azure-sql-database access-token azure-msi

我正在尝试获取Azure应用服务应用程序以利用托管服务身份(MSI)并连接到Azure SQL数据库,但是.NET Framework 4.7应用程序在启动时失败,并出现以下错误:

System.Data.SqlClient.SqlException: Login failed for user ''.
System.InvalidOperationException: This operation requires a connection to the 'master' database. Unable to create a connection to the 'master' database because the original database connection has been opened and credentials have been removed from the connection string. Supply an unopened connection. ---> System.Data.SqlClient.SqlException: Login failed for user ''.

我添加了Microsoft.Azure.Services.AppAuthentication和Microsoft.IdentityModel.Clients.ActiveDirectory nuget程序包。

我已在门户中为应用程序服务启用了系统分配的身份。

我将Active Directory用户组设置为Azure SQL服务器的Active Directory管理员。

我在数据库上执行了EXTERNAL PROVIDER命令中的CREATE USER“ [user here]”。我可能忘记了为数据库用户(MSI)添加/修改角色的机会。但是,如果是这种情况,我不会指望该错误。

应用程序的DbContext具有两个构造函数,其中一个如下:

    public ApplicationDbContext(SqlConnection sqlConnection) : base(sqlConnection, true)
    {
        var isRunningLocal = string.IsNullOrEmpty(Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME"));

        sqlConnection.ConnectionString = ConfigurationManager.ConnectionStrings[nameof(ApplicationDbContext)].ConnectionString;

        if (!isRunningLocal)
        {
            sqlConnection.AccessToken = new AzureServiceTokenProvider("RunAs=App").GetAccessTokenAsync("https://database.windows.net/").Result;
        }

        Database.SetInitializer<ApplicationDbContext>(null);
        //Database.SetInitializer(new MigrateDatabaseToLatestVersion<ApplicationDbContext, Migrations.Configuration>());
    }

请注意,有两个Database.SetInitializer()调用,一个带有空参数,另一个带有MigrateDatabaseToLatestVersion参数,并且已注释掉。使用前一个选项时,应用程序将运行。如果我注释掉前者而取消注释后者,则在应用程序启动时会引发异常。

为什么异常描述包含一个空('')用户?我怀疑实体框架(EF)迁移与数据库上MSI的身份验证冲突。我遇到了一些与我的问题有关的搜索引擎结果中的一个,但是答案是不够的:

https://github.com/MicrosoftDocs/azure-docs/issues/13801 我想像过去一样继续使用数据库迁移。即使数据库已经存在,问题似乎也会发生。

任何帮助将不胜感激。谢谢!

1 个答案:

答案 0 :(得分:0)

能否请您尝试使用以bool作为参数并将其设置为true的 MigrateDatabaseToLatestVersion 构造函数?否则,它将使用来自使用默认构造函数或注册工厂(如果适用)构造的上下文的连接信息

根据documentation如果设置为true,则使用来自触发初始化的上下文的连接信息来运行初始化程序。否则,连接信息将从使用默认构造函数或注册工厂(如果适用)构造的上下文中获取