使用 SQLProvider 和 MemberShip 的 ASP.Net 应用程序在使用 Azure 托管标识时无法连接到 DB

ASP.Net Application which uses SQLProvider and MemberShip Fails to connect to DB when using Azure Managed Identity

提问人:Kumar 提问时间:10/30/2023 更新时间:11/2/2023 访问量:44

问:

从 SQL Server 身份验证迁移到 Azure 托管标识时,我们面临以下登录问题

异常信息: 异常类型:SqlException 异常消息:用户“”登录失败。 在 System.Data.SqlClient.SqlInternalConnectionTds。ctor(DbConnectionPoolIdentity 标识、SqlConnectionString connectionOptions、SqlCredential 凭据、Object providerInfo、String newPassword、SecureString newSecurePassword、Boolean redirectedUserInstance、SqlConnectionString userConnectionOptions、SessionData reconnectSessionData、DbConnectionPool pool、String accessToken、Boolean applyTransientFaultHandling、SqlAuthenticationProviderManager sqlAuthProviderManager) 在 System.Data.SqlClient.SqlConnectionFactory.CreateConnection (DbConnectionOptions 选项、 DbConnectionPoolKey poolKey、 对象 poolGroupProviderInfo、 DbConnectionPool 池、 DbConnection owningConnection、 DbConnectionOptions 用户选项) 在 System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection (DbConnectionPool 池、 DbConnection owningObject、 DbConnectionOptions 选项、 DbConnectionPoolKey poolKey、 DbConnectionOptions 用户选项) 在 System.Data.ProviderBase.DbConnectionPool.CreateObject (DbConnection owningObject、 DbConnectionOptions 用户选项、 DbConnectionInternal oldConnection) 在 System.Data.ProviderBase.DbConnectionPool.UserCreateRequest (DbConnection owningObject、 DbConnectionOptions 用户选项、 DbConnectionInternal oldConnection) 在 System.Data.ProviderBase.DbConnectionPool.TryGetConnection (DbConnection owningObject、UInt32 waitForMultipleObjectsTimeout、 布尔值 allowCreate、 布尔值 onlyOneCheckConnection、 DbConnectionOptions userOptions、 DbConnectionInternal& 连接) 在 System.Data.ProviderBase.DbConnectionPool.TryGetConnection (DbConnection owningObject、 TaskCompletionSource1 重试、 DbConnectionOptions userOptions、 DbConnectionInternal oldConnection、 DbConnectionInternal& 连接) 在 System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal (DbConnection outerConnection、 DbConnectionFactory connectionFactory、 TaskCompletionSource1 重试) 在 System.Data.SqlClient.SqlConnection.TryOpen (TaskCompletionSource'1 重试) 在 System.Data.SqlClient.SqlConnection.Open() 在 System.Web.DataAccess.SqlConnectionHolder.Open (HttpContext 上下文,布尔值 revertImpersonate) 在 System.Web.DataAccess.SqlConnectionHelper.GetConnection (字符串 connectionString,布尔值 revertImpersonation) 在 System.Web.Security.SqlRoleProvider.GetRolesForUser (字符串用户名) 在 System.Web.Security.RolePrincipal.IsInRole (字符串角色) 在 System.Web.Configuration.AuthorizationRule.IsTheUserInAnyRole (StringCollection 角色,IPrincipal 主体) 在 System.Web.Configuration.AuthorizationRule.IsUserAllowed (IPrincipal 用户,字符串谓词) 在 System.Web.Configuration.AuthorizationRuleCollection.IsUserAllowed (IPrincipal 用户,字符串谓词) 在 System.Web.Security.UrlAuthorizationModule.OnEnter (对象源,EventArgs eventArgs) 在 System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() 在 System.Web.HttpApplication.ExecuteStepImpl (IExecutionStep 步骤) 在 System.Web.HttpApplication.ExecuteStep (IExecutionStep 步骤,布尔值&完成同步)1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource1 retry, DbConnectionOptions userOptions) at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource

下面是 web.config

<system.web>
<roleManager enabled="true" cacheRolesInCookie="true" 
defaultProvider="CustomizedRoleProvider" cookieTimeout="60">
 <providers>
    <clear />
    <add connectionStringName="ProjectConnection" 
  type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, 
  Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" applicationName="/" 
  name="CustomizedRoleProvider" />
  </providers>
 </roleManager>
 <membership defaultProvider="CustomizedProvider">
  <providers>
    <remove name="AspNetSqlMembershipProvider" />
    <add connectionStringName="ProjectConnection" enablePasswordRetrieval="false" 
    enablePasswordReset="true" requiresQuestionAndAnswer="false" applicationName="/" 
   requiresUniqueEmail="true" passwordFormat="Hashed" 
   maxInvalidPasswordAttempts="3" minRequiredNonalphanumericCharacters="1" 
   passwordAttemptWindow="3" minRequiredPasswordLength="8" 
   passwordStrengthRegularExpression="^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,16}$" 
     name="CustomizedProvider" type="System.Web.Security.SqlMembershipProvider, 
   System.Web, Version=2.0.0.0,   Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
   </providers>
    </membership>
   <authentication mode="Forms">
       <forms slidingExpiration="true" loginUrl="Login/Login" defaultUrl="~/" 
      timeout="10800" requireSSL="false" protection="All" />
   </authentication>
  <authorization>
   <deny users="?" />
    <allow roles="Admin" />
   </authorization>
   <customErrors mode="Off" />
  </system.web>
 <connectionStrings>
  <add name="ProjectConnection" 
  connectionString="Server=tcp:xx.database.windows.net,1433;Database=xx;" />
   </connectionStrings>
C# asp.net sql-server azure-active-directory azure-web-app-service

评论


答:

0赞 SiddheshDesai 11/2/2023 #1

我参考了这个 MS 文档并创建了一个连接到 Azure SQL 的文档,它在部署后成功加载,如下所示:-Asp.Net app

enter image description here

现在,为了成功启用托管标识,我引用了此 MS Document2 将我的 Azure Web 应用托管标识与 Azure SQL 连接,如下所示:-

  1. 我在我的 Azure SQL 服务器中添加了一个用户作为管理员,如下所示:-

enter image description here

  1. 然后我访问了我的 Azure Web 应用>环境变量>连接字符串,并将下面的 ConnectionString 添加到 MyDbConnection:-
"Server=tcp:sqlservername.database.windows.net;Authentication=Active Directory Default; Database=dotnetsiliconsqldb;"

可以在本地 web.config 文件中更新此连接字符串,也可以在 asp.net 代码中更新appsettings.json文件

  1. 现在,启用 Azure Web 应用托管标识,并将其所需的角色分配给 Azure SQL,如下所示:-

enter image description here

使用 Azure AD 凭据连接到 Azure SQL Server,并运行以下命令以添加 Web 应用托管标识角色以访问 Azure SQL。

Web 应用托管标识的名称与 Web 应用的名称相同:-

SQL查询:-

CREATE USER [web-app-name<identity-name>] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [web-app-name<identity-name>];
ALTER ROLE db_datawriter ADD MEMBER [web-app-name<identity-name>];
ALTER ROLE db_ddladmin ADD MEMBER [web-app-name<identity-name>];
GO

请确保选中“允许 Azure 服务和资源访问此服务器”,以便我们的 Web 应用通过防火墙访问 Azure SQL Server。我还允许从我的 Azure SQL 中的所有 IP 进行连接:-:-

enter image description here

可以参考 Mark McGookin 的 SO 答案 - 使用托管标识和 VSCode - Stack Overflow 将本地 asp dotnet 核心应用连接到 Azure SQL,以通过 Azure CLI 执行所有这些步骤。