IIS 无法将 windows 凭据传递到 SQL 服务器以用于 ASP.NET 核心应用
IIS fails to pass windows credentials through to SQL Server for ASP.NET Core app
我在一家拥有内部网的大公司工作,Windows 每个人都可以登录 AD。我们有许多内部 SQL 服务器数据库,允许我们使用 Windows 身份验证登录,我正尝试通过 ASP.NET 核心应用程序连接其中之一。我可以通过 SQL Server Management Studio 连接到这个数据库并查询表。
我已经尽可能地按照 ASP.NET Core app using an existing database 的教程进行操作,并创建了一个模型 class 来测试我是否可以从数据库中读取数据。在 Visual Studio 中使用 IIS Express 进行调试时,我可以在访问自动生成的控制器和视图时从数据库中读取数据。
调试时一切正常,但发布到 IIS 时,出现以下错误:
SqlException: Login failed for user '<DOMAIN>\<COMPUTERNAME>$'.
其中 domain 是我的域,computername 是我的计算机名称。这是预料之中的,因为我的计算机本身无法访问数据库。但它不应该尝试使用该系统帐户(带有美元符号)进行连接,它应该尝试连接我的 windows 帐户:<DOMAIN>\<USERNAME>
.
奇怪的是,应用程序 确实 似乎在某种程度上识别了我的 Windows 凭据 - 当我访问主页时,我得到了熟悉的 "Hello, <DOMAIN>\<USERNAME>!"
导航栏中的消息。因此 Windows 凭据肯定会传递给应用程序,但由于某种原因在尝试通过 DbContext 连接到数据库时没有传递。
我是不是漏掉了什么明显的东西?
我的代码
我从 Visual Studio 的 ASP.NET 核心 Web 应用程序模板开始。
在launchSettings.json中,我有:
"iisSettings": {
"windowsAuthentication": true,
"anonymousAuthentication": false,
"iisExpress": {
"applicationUrl": "http://localhost:60686",
"sslPort": 44336
}
},
在appsettings.json中,我有:
"ConnectionStrings": {
"MyDB": "Server=<servername>;Database=<dbname>;Trusted_Connection=True;"
},
在Startup.cs中,我在ConfigureServices
中有以下行
services.AddDbContext<MyContext>(options => {
options.UseSqlServer(Configuration.GetConnectionString("MyDB"));
});
从那里开始,我使用 Entity Framework 构建了一个带有视图的 MVC 控制器。
IIS 已将 Windows 身份验证设置为是,将匿名身份验证设置为否。我的应用程序池设置为无托管代码和 ApplicationPoolIdentity。
编辑:问题
为了说明我试图解决的实际问题,我在远程 Intranet 服务器上有一个 SQL 服务器数据库,它允许通过 Windows 身份验证访问整个公司的一个子集。如果我想创建一个 ASP.NET 应用程序来为由 IIS 托管的该数据库提供 API,最好的方法是什么?假设:
- 我不想自己管理权限或以某种方式复制它们
- 可以直接访问数据库的人应该可以访问 API,不能访问的人则不应该。
- 如果他们在登录 Windows 时从内部网访问它,则他们不必再次登录。
我以为我可以通过应用程序将他们的 windows 凭据从 IIS 传递到 SQL 服务器,但我开始怀疑是否真的如此。
您正在使用 SqlServer 实体框架,而 EF 正在使用 ADO.NET SqlClient。因此 Trusted_Connection=yes;
不起作用。
改为添加 Integrated Security=true;
,它应该会被修复。
这里有一些资源可以阅读
https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/connection-string-syntax
在详细了解 .NET 以及 Windows auth 在 IIS 上实际执行的操作后,我要说的是,不推荐我尝试执行的操作。将 windows 凭据传递给 .NET 应用程序以便从中读取,与实际以该用户身份执行辅助进程之间存在差异。后一种情况是我试图做的,但应该在 IIS 中使用可以登录数据库的用户设置我的应用程序池,并使用 windows 凭据来验证拥有的用户列表访问。
不是挖掘旧线程,但只要设置了 Identity Impersonate = True,这个函数就应该可以工作。这里有一些正在处理的东西。
我会添加我的答案,因为这是我解决这个问题的方法。
向登录名添加“$”符号的原因 name/user 必须与托管应用程序的 IIS 有关。
我不是这方面的专家,所以我不能真正深入,但我已经将 IIS 用户添加到登录名中,然后就可以了。
USE [master]
GO
CREATE LOGIN [IIS APPPOOL\'name'] FROM WINDOWS WITH DEFAULT_DATABASE=[master], DEFAULT_LANGUAGE=[us_english]
GO
ALTER SERVER ROLE [sysadmin] ADD MEMBER [IIS APPPOOL\'name']
GO
ALTER SERVER ROLE [securityadmin] ADD MEMBER [IIS APPPOOL\'name']
GO
ALTER SERVER ROLE [serveradmin] ADD MEMBER [IIS APPPOOL\'name']
GO
ALTER SERVER ROLE [setupadmin] ADD MEMBER [IIS APPPOOL\'name']
GO
ALTER SERVER ROLE [processadmin] ADD MEMBER [IIS APPPOOL\'name']
GO
ALTER SERVER ROLE [diskadmin] ADD MEMBER [IIS APPPOOL\'name']
GO
ALTER SERVER ROLE [dbcreator] ADD MEMBER [IIS APPPOOL\'name']
GO
ALTER SERVER ROLE [bulkadmin] ADD MEMBER [IIS APPPOOL\'name']
GO
您必须将 'name' 更改为您的 IIS 托管应用程序名称。因此,例如,如果您 app/site 在 ISS 中的名称是“My-Backend-App”,您应该这样做:
CREATE LOGIN [IIS APPPOOL\My-Backend-App] FROM WINDOWS ...
因此所有名称都应为“My-Backend-App”。
将此用户添加到登录名时,我的后端应用程序可以访问和创建数据库、创建表、访问数据等...
旁注: 我使用 Windows 事件记录器发现这是我的问题。我的应用程序刚刚崩溃,显示“500.30”错误但未提供真实信息。
您可以通过 Windows 搜索访问“事件查看器”应用程序。然后你可以转到“应用程序”,那里有你机器上出现的所有应用程序 errors/crashes,在这种情况下还有原因。它表示在尝试登录 SQL 时找不到用户“myUser$”,但 Windows 身份验证用户是“myUser”。所以出于某种原因,它添加了一个“$”符号并且无法登录。我上面的修复解决了这个问题,你可以登录等等。
我在一家拥有内部网的大公司工作,Windows 每个人都可以登录 AD。我们有许多内部 SQL 服务器数据库,允许我们使用 Windows 身份验证登录,我正尝试通过 ASP.NET 核心应用程序连接其中之一。我可以通过 SQL Server Management Studio 连接到这个数据库并查询表。
我已经尽可能地按照 ASP.NET Core app using an existing database 的教程进行操作,并创建了一个模型 class 来测试我是否可以从数据库中读取数据。在 Visual Studio 中使用 IIS Express 进行调试时,我可以在访问自动生成的控制器和视图时从数据库中读取数据。
调试时一切正常,但发布到 IIS 时,出现以下错误:
SqlException: Login failed for user '<DOMAIN>\<COMPUTERNAME>$'.
其中 domain 是我的域,computername 是我的计算机名称。这是预料之中的,因为我的计算机本身无法访问数据库。但它不应该尝试使用该系统帐户(带有美元符号)进行连接,它应该尝试连接我的 windows 帐户:<DOMAIN>\<USERNAME>
.
奇怪的是,应用程序 确实 似乎在某种程度上识别了我的 Windows 凭据 - 当我访问主页时,我得到了熟悉的 "Hello, <DOMAIN>\<USERNAME>!"
导航栏中的消息。因此 Windows 凭据肯定会传递给应用程序,但由于某种原因在尝试通过 DbContext 连接到数据库时没有传递。
我是不是漏掉了什么明显的东西?
我的代码
我从 Visual Studio 的 ASP.NET 核心 Web 应用程序模板开始。
在launchSettings.json中,我有:
"iisSettings": {
"windowsAuthentication": true,
"anonymousAuthentication": false,
"iisExpress": {
"applicationUrl": "http://localhost:60686",
"sslPort": 44336
}
},
在appsettings.json中,我有:
"ConnectionStrings": {
"MyDB": "Server=<servername>;Database=<dbname>;Trusted_Connection=True;"
},
在Startup.cs中,我在ConfigureServices
services.AddDbContext<MyContext>(options => {
options.UseSqlServer(Configuration.GetConnectionString("MyDB"));
});
从那里开始,我使用 Entity Framework 构建了一个带有视图的 MVC 控制器。
IIS 已将 Windows 身份验证设置为是,将匿名身份验证设置为否。我的应用程序池设置为无托管代码和 ApplicationPoolIdentity。
编辑:问题
为了说明我试图解决的实际问题,我在远程 Intranet 服务器上有一个 SQL 服务器数据库,它允许通过 Windows 身份验证访问整个公司的一个子集。如果我想创建一个 ASP.NET 应用程序来为由 IIS 托管的该数据库提供 API,最好的方法是什么?假设:
- 我不想自己管理权限或以某种方式复制它们
- 可以直接访问数据库的人应该可以访问 API,不能访问的人则不应该。
- 如果他们在登录 Windows 时从内部网访问它,则他们不必再次登录。
我以为我可以通过应用程序将他们的 windows 凭据从 IIS 传递到 SQL 服务器,但我开始怀疑是否真的如此。
您正在使用 SqlServer 实体框架,而 EF 正在使用 ADO.NET SqlClient。因此 Trusted_Connection=yes;
不起作用。
改为添加 Integrated Security=true;
,它应该会被修复。
这里有一些资源可以阅读 https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/connection-string-syntax
在详细了解 .NET 以及 Windows auth 在 IIS 上实际执行的操作后,我要说的是,不推荐我尝试执行的操作。将 windows 凭据传递给 .NET 应用程序以便从中读取,与实际以该用户身份执行辅助进程之间存在差异。后一种情况是我试图做的,但应该在 IIS 中使用可以登录数据库的用户设置我的应用程序池,并使用 windows 凭据来验证拥有的用户列表访问。
不是挖掘旧线程,但只要设置了 Identity Impersonate = True,这个函数就应该可以工作。这里有一些正在处理的东西。
我会添加我的答案,因为这是我解决这个问题的方法。
向登录名添加“$”符号的原因 name/user 必须与托管应用程序的 IIS 有关。
我不是这方面的专家,所以我不能真正深入,但我已经将 IIS 用户添加到登录名中,然后就可以了。
USE [master]
GO
CREATE LOGIN [IIS APPPOOL\'name'] FROM WINDOWS WITH DEFAULT_DATABASE=[master], DEFAULT_LANGUAGE=[us_english]
GO
ALTER SERVER ROLE [sysadmin] ADD MEMBER [IIS APPPOOL\'name']
GO
ALTER SERVER ROLE [securityadmin] ADD MEMBER [IIS APPPOOL\'name']
GO
ALTER SERVER ROLE [serveradmin] ADD MEMBER [IIS APPPOOL\'name']
GO
ALTER SERVER ROLE [setupadmin] ADD MEMBER [IIS APPPOOL\'name']
GO
ALTER SERVER ROLE [processadmin] ADD MEMBER [IIS APPPOOL\'name']
GO
ALTER SERVER ROLE [diskadmin] ADD MEMBER [IIS APPPOOL\'name']
GO
ALTER SERVER ROLE [dbcreator] ADD MEMBER [IIS APPPOOL\'name']
GO
ALTER SERVER ROLE [bulkadmin] ADD MEMBER [IIS APPPOOL\'name']
GO
您必须将 'name' 更改为您的 IIS 托管应用程序名称。因此,例如,如果您 app/site 在 ISS 中的名称是“My-Backend-App”,您应该这样做:
CREATE LOGIN [IIS APPPOOL\My-Backend-App] FROM WINDOWS ...
因此所有名称都应为“My-Backend-App”。
将此用户添加到登录名时,我的后端应用程序可以访问和创建数据库、创建表、访问数据等...
旁注: 我使用 Windows 事件记录器发现这是我的问题。我的应用程序刚刚崩溃,显示“500.30”错误但未提供真实信息。
您可以通过 Windows 搜索访问“事件查看器”应用程序。然后你可以转到“应用程序”,那里有你机器上出现的所有应用程序 errors/crashes,在这种情况下还有原因。它表示在尝试登录 SQL 时找不到用户“myUser$”,但 Windows 身份验证用户是“myUser”。所以出于某种原因,它添加了一个“$”符号并且无法登录。我上面的修复解决了这个问题,你可以登录等等。