【问题标题】:Why can't I read a SQL Server database table using a Windows group for Windows authentication?为什么我不能使用 Windows 组读取 SQL Server 数据库表以进行 Windows 身份验证?
【发布时间】:2018-07-16 16:32:27
【问题描述】:

我的目标是通过 C# 应用程序为 Windows 组 TestDbAccess 的成员提供对 [Test].[dbo].[Persons] 的读取访问权限。

问题

  • 当我使用domain admin account 登录计算机C2.foo.gov 并执行程序(见下文)时,程序读取数据库并按预期在网格中显示一条记录(所以我知道代码是好的)。

  • 当我使用ssmith@foo.gov 帐户登录计算机C2.foo.gov 并执行程序时,我收到一个SQL Server 错误Login failed for user 'foo\ssmith'. Reason: Could not find a login matching the name provided. [CLIENT: xxx.xx.xx.xxx]。 (错误在SQL Server 错误日志中)

为什么我无法使用 Windows 组读取我的 SQL Server 数据库表以进行 Windows 身份验证?

这是我所拥有的:

  • 所有计算机、用户和组都是 foo.gov 域的成员

  • 域位于未连接的 enclave 中。所有防火墙均已关闭。

  • SQL Server(默认实例)安装在计算机 C1.foo.gov 上。有数据库Test 和表[dbo].[persons]。 [Test].[dbo].[Persons] 有一条记录。该数据库是使用具有Server Rolespublic 和sysadmin 的域管理员帐户创建的。具有User Mapping 的db_owner 和public 到Test 数据库。

  • SQL Server(默认实例)具有安全登录 foo\TestDbAccess。 Server Role 是 public。 User mapping 是 db_datareader 和 public 用于数据库 Test,user = foo\TestDbAccess,default schema = dbo。状态:Permission to connect to database engine=Grant。 Login=Enabled

  • 用户ssmith@foo.gov存在于Active Directory Users and Computers中

  • TestDbAccess 组存在于Active Directory Users and Computers 中。范围是Global。类型是Security

  • ssmith@foo.gov 是TestDbAccess 的成员

代码如下。

app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
    </startup>
    <connectionStrings>
        <add name="DbConnectionString"
            connectionString="Data Source=C1;Initial Catalog=Test;Integrated Security=True;Trusted_Connection=True;Connection Timeout=10"
            providerName="System.Data.SqlClient" />
    </connectionStrings>
</configuration>

数据库访问类

using System.Data;
using System.Data.SqlClient;

namespace DbAccessWindowsGroups
{
    public static class DatabaseAccess
    {
        internal static DataTable GetData()
        {
            DataTable dataTable_TableList = new DataTable
            {
                TableName = "test"
            };

            try
            {

                using (SqlConnection sqlConnection = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["DbConnectionString"].ToString()))
                {
                    using (SqlCommand sqlCommand = new SqlCommand())
                    {

                        sqlCommand.Connection = sqlConnection;
                        sqlCommand.CommandType = CommandType.Text;
                        sqlCommand.CommandText = "SELECT TOP 1000 [Test].[dbo].[Persons].[iuid], [Test].[dbo].[Persons].[Name] FROM [Test].[dbo].[Persons]";
                        sqlConnection.Open();

                        SqlDataReader sqlDataReader = sqlCommand.ExecuteReader();
                        dataTable_TableList.Load(sqlDataReader);
                    }
                }
            }
            catch
            {
                throw;
            }

            return dataTable_TableList;
        }
    }
}

Form1 类

using System;
using System.Data;
using System.Windows.Forms;

namespace DbAccessWindowsGroups
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Button1_Click(object sender, EventArgs e)
        {
            try
            {
                BindingSource bindingSource = new BindingSource();
                dataGridView1.DataSource = null;
                DataTable dataTable = DatabaseAccess.GetData();
                bindingSource.DataSource = dataTable;
                dataGridView1.DataSource = bindingSource;
            }
            catch (Exception ex)
            {
                Program._DisplayMessage("Error", ex, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}

【问题讨论】:

  • 您的详细信息非常详尽。谢谢!请确认 ssmith 在域 FOO 中,并且作为登录名启用,然后该 ssmith 在组 foo\testdbaccess 中。该错误表明用户无权访问。那么当你在 master 中运行时你会看到什么(不要发布 SID):“select * from sys.syslogins where [loginname] = 'foo\testdbaccess';”然后切换到测试数据库,让我知道您看到的“select * from sys.database_principals where [name] = 'foo\testdbaccess';”这应该可以帮助我们解决这个问题。
  • 16 小时有何不同。在 7/16 发布我的问题后,我需要在 C1 上安装 Windows 更新。我这样做了,重新启动了 C1,然后回家了。当我今天早上回来时,我开始收集您问题的答案,但随后决定使用ssmith@foo.gov 登录在计算机 C2 上重新运行我的程序。有效。所以,我必须假设重新启动计算机 C1 和/或让我的Active Directory 更改有足够的时间(将组TestDbAccess 添加到A.D. 和SQL Server)来传播成功了吗?想法?
  • 有道理。请将答案发布为答案并将其标记为已解决。

标签: c# sql-server winforms active-directory windows-authentication


【解决方案1】:

事实证明,我的代码是有效的。在 7 月 16 日发布我的问题后,我需要在计算机 C1 上安装 Windows 更新。我这样做了,重新启动了 C1,然后回家了。第二天早上回来时,我决定使用 ssmith@foo.gov 登录名重新尝试在计算机 C2 上运行我的程序。有效。因此,我必须假设重新启动计算机 C1 和/或让我的 Active Directory 更改(将组 TestDbAccess 添加到 AD 和 SQL Server)传递足够的时间来传播就可以了。

【讨论】:

    猜你喜欢
    • 2020-12-22
    • 2019-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-14
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    相关资源
    最近更新 更多