在使用托管ODP.NET时,如何从C#查询LDAP以解析Oracle TNS主机名?

在使用托管ODP.NET时,如何从C#查询LDAP以解析Oracle TNS主机名?,c#,oracle,ldap,directoryentry,tnsnames,C#,Oracle,Ldap,Directoryentry,Tnsnames,除了我之前的问题(我设法用它来回答自己),我现在还有另一个问题,这是从前面的问题(提供背景资料)开始的 我希望直接从我的C#代码查询LDAP,以执行Oracle TNS主机名的LDAP查找,以获取连接字符串。这通常存储在tnsnames.ora中,我的组织使用LDAP(通过LDAP.ora)从使用Active Directory的LDAP服务器解析主机名 但是,我在我的C#应用程序中使用(Oracle.ManagedDataAccess.dll),该应用程序不支持前面提到的中提到的LDAP。这就

除了我之前的问题(我设法用它来回答自己),我现在还有另一个问题,这是从前面的问题(提供背景资料)开始的

我希望直接从我的C#代码查询LDAP,以执行Oracle TNS主机名的LDAP查找,以获取连接字符串。这通常存储在tnsnames.ora中,我的组织使用LDAP(通过LDAP.ora)从使用Active Directory的LDAP服务器解析主机名

但是,我在我的C#应用程序中使用(Oracle.ManagedDataAccess.dll),该应用程序不支持前面提到的中提到的LDAP。这就是我希望直接从C#查询LDAP的原因

我用
DirectoryEntry
DirectorySearcher
找到了一种方法来实现这一点,但我不知道将什么作为
DirectorySearcher
的参数。我可以访问ldap.ora,其格式如下:

#LDAP.ORA配置
#由Oracle配置工具生成。
DEFAULT\u ADMIN\u CONTEXT=“dc=xx,dc=mycompany,dc=com”
目录服务器=(ldap服务器1.mycompany.com:389:636,ldap服务器2.mycompany.com:389:636,…)目录服务器类型=OID


但是,如何将此映射到在我的C#代码中设置LDAP查询?

要开始,请尝试:

using System.DirectoryServices;
...

DirectoryEntry de = new DirectoryEntry();
de.Username = "username@mysite.com";
de.Password = "password";
de.Path = "LDAP://DC=mysite,DC=com";
de.AuthenticationType = AuthenticationTypes.Secure;
DirectorySearcher des = new DirectorySearcher(de);

现在,您应该能够使用所述的DirectorySearcher(filter、findone等)访问ldap了

根据我在中找到的内容判断,代码应该如下所示:

string directoryServer = "ldap_server1.mycompany.com:389";
string defaultAdminContext = "dc=xx,dc=mycompany,dc=com";
string oracleHostEntryPath = string.Format("LDAP://{0}/cn=OracleContext,{1}", directoryServer, defaultAdminContext);

var directoryEntry = new DirectoryEntry(oracleHostEntryPath) {AuthenticationType = AuthenticationTypes.None};
var directorySearcher = new DirectorySearcher(directoryEntry, "(&(objectclass=orclNetService)(cn=ABCDEFG1))", new[] { "orclnetdescstring" }, SearchScope.Subtree);

string oracleNetDescription = Encoding.Default.GetString(des.FindOne().Properties["orclnetdescstring"][0] as byte[]);

关于我在中的第二条评论,这是执行LDAP查找的代码,它改进了我找到的原始版本。它还处理ldap.ora文件中包含多个分隔端口号的服务器列表

private static string ResolveServiceNameLdap(string serviceName)
{
    string tnsAdminPath = Path.Combine(@"C:\Apps\oracle\network\admin", "ldap.ora");
    string connectionString = string.Empty;

    // ldap.ora can contain many LDAP servers
    IEnumerable<string> directoryServers = null;

    if (File.Exists(tnsAdminPath))
    {
        string defaultAdminContext = string.Empty;

        using (var sr = File.OpenText(tnsAdminPath))
        {
            string line;

            while ((line = sr.ReadLine()) != null)
            {
                // Ignore commetns
                if (line.StartsWith("#"))
                {
                    continue;
                }

                // Ignore empty lines
                if (line == string.Empty)
                {
                    continue;
                }

                // If line starts with DEFAULT_ADMIN_CONTEXT then get its value
                if (line.StartsWith("DEFAULT_ADMIN_CONTEXT"))
                {
                    defaultAdminContext = line.Substring(line.IndexOf('=') + 1).Trim(new[] {'\"', ' '});
                }

                // If line starts with DIRECTORY_SERVERS then get its value
                if (line.StartsWith("DIRECTORY_SERVERS"))
                {
                    string[] serversPorts = line.Substring(line.IndexOf('=') + 1).Trim(new[] {'(', ')', ' '}).Split(',');
                    directoryServers = serversPorts.SelectMany(x =>
                    {
                        // If the server includes multiple port numbers, this needs to be handled
                        string[] serverPorts = x.Split(':');
                        if (serverPorts.Count() > 1)
                        {
                            return serverPorts.Skip(1).Select(y => string.Format("{0}:{1}", serverPorts.First(), y));
                        }

                        return new[] {x};
                    });
                }
            }
        }

        // Iterate through each LDAP server, and try to connect
        foreach (string directoryServer in directoryServers)
        {
            // Try to connect to LDAP server with using default admin contact
            try
            {
                var directoryEntry = new DirectoryEntry("LDAP://" + directoryServer + "/" + defaultAdminContext, null, null, AuthenticationTypes.Anonymous);
                var directorySearcher = new DirectorySearcher(directoryEntry, "(&(objectclass=orclNetService)(cn=" + serviceName + "))", new[] { "orclnetdescstring" }, SearchScope.Subtree);

                SearchResult searchResult = directorySearcher.FindOne();

                var value = searchResult.Properties["orclnetdescstring"][0] as byte[];

                if (value != null)
                {
                    connectionString = Encoding.Default.GetString(value);
                }

                // If the connection was successful, then not necessary to try other LDAP servers
                break;
            }
            catch
            {
                // If the connection to LDAP server not successful, try to connect to the next LDAP server
                continue;
            }
        }

        // If casting was not successful, or not found any TNS value, then result is an error message
        if (string.IsNullOrEmpty(connectionString))
        {
            connectionString = "TNS value not found in LDAP";
        }
    }
    else
    {
        // If ldap.ora doesn't exist, then return error message
        connectionString = "ldap.ora not found";
    }

    return connectionString;
}
私有静态字符串ResolveServiceNameLdap(字符串serviceName)
{
字符串tnsAdminPath=Path.Combine(@“C:\Apps\oracle\network\admin”、“ldap.ora”);
string connectionString=string.Empty;
//ora可以包含许多ldap服务器
IEnumerable directoryServers=null;
if(File.Exists(tnsAdminPath))
{
string defaultAdminContext=string.Empty;
使用(var sr=File.OpenText(tnsAdminPath))
{
弦线;
而((line=sr.ReadLine())!=null)
{
//忽略命令
if(第行开始,以“#”号填列)
{
继续;
}
//忽略空行
if(line==string.Empty)
{
继续;
}
//如果行以默认的\u ADMIN\u上下文开头,则获取其值
if(line.StartsWith(“默认的\u管理\u上下文”))
{
defaultAdminContext=line.Substring(line.IndexOf('=')+1.Trim(new[]{'\',''});
}
//如果行以目录\服务器开始,则获取其值
if(line.StartsWith(“目录\服务器”))
{
string[]serversPorts=line.Substring(line.IndexOf('=')+1).Trim(new[]{'(','),'}).Split(',');
directoryServers=serversPorts.SelectMany(x=>
{
//如果服务器包含多个端口号,则需要处理此问题
字符串[]serverPorts=x.Split(“:”);
如果(serverPorts.Count()>1)
{
返回serverPorts.Skip(1)。选择(y=>string.Format(“{0}:{1}”,serverPorts.First(),y));
}
返回新的[]{x};
});
}
}
}
//迭代每个LDAP服务器,并尝试连接
foreach(directoryServer中的字符串directoryServer)
{
//尝试使用默认管理员联系人连接到LDAP服务器
尝试
{
var directoryEntry=new directoryEntry(“LDAP://”+directoryServer+“//”+defaultAdminContext,null,null,AuthenticationTypes.Anonymous);
var directorySearcher=new directorySearcher(directoryEntry,(&(objectclass=orclNetService)(cn=“+serviceName+”),new[]{“orclnetdescstring”},SearchScope.Subtree);
SearchResult SearchResult=directorySearcher.FindOne();
var value=searchResult.Properties[“orclnetdescstring”][0]作为字节[];
if(值!=null)
{
connectionString=Encoding.Default.GetString(值);
}
//如果连接成功,则无需尝试其他LDAP服务器
打破
}
抓住
{
//如果到LDAP服务器的连接不成功,请尝试连接到下一个LDAP服务器
继续;
}
}
//若转换未成功,或未找到任何TNS值,则结果为错误消息
if(string.IsNullOrEmpty(connectionString))
{
connectionString=“在LDAP中找不到TNS值”;
}
}
其他的
{
//如果ldap.ora不存在,则返回错误消息
connectionString=“ldap.ora未找到”;
}
返回连接字符串;
}

以下是基于其他答案的更完整示例:

using System;
using System.Data;
using System.DirectoryServices;
using System.Text;
using Oracle.ManagedDataAccess.Client;

namespace BAT
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            string directoryServer = "myServer:389";
            string defaultAdminContext = "cn=OracleContext,dc=world";
            string serviceName = "MYDB";
            string userId = "MYUSER";
            string password = "MYPW";

            using (IDbConnection connection = GetConnection(directoryServer, defaultAdminContext, serviceName, userId,
                    password))
            {
                connection.Open();

                connection.Close();
            }

        }

        private static IDbConnection GetConnection(string directoryServer, string defaultAdminContext,
            string serviceName, string userId, string password)
        {
            string descriptor = ConnectionDescriptor(directoryServer, defaultAdminContext, serviceName);
            // Connect to Oracle
            string connectionString = $"user id={userId};password={password};data source={descriptor}";

            OracleConnection con = new OracleConnection(connectionString);
            return con;
        } 

        private static string ConnectionDescriptor(string directoryServer, string defaultAdminContext,
            string serviceName)
        {
            string ldapAdress = $"LDAP://{directoryServer}/{defaultAdminContext}";
            string query = $"(&(objectclass=orclNetService)(cn={serviceName}))";
            string orclnetdescstring = "orclnetdescstring";

            DirectoryEntry directoryEntry = new DirectoryEntry(ldapAdress, null, null, AuthenticationTypes.Anonymous);
            DirectorySearcher directorySearcher = new DirectorySearcher(directoryEntry, query, new[] { orclnetdescstring },
                SearchScope.Subtree);

            SearchResult searchResult = directorySearcher.FindOne();
            byte[] value = searchResult.Properties[orclnetdescstring][0] as byte[];

            if (value != null)
            {
                string descriptor = Encoding.Default.GetString(value);
                return descriptor;
            }

            throw new Exception("Error querying LDAP");
        }
    }
}

您尝试过什么?在C#中,您可能会设置DirectorySearcher是的,正如我在问题中提到的,我使用了
DirectorySearcher
,但我不知道基于ldap.ora文件将什么作为
DirectorySearcher
的参数。好的,但我的问题更多的是如何将ldap.ora文件映射到此C#代码。什么进入“mysite”?我是否在“username”和“password”中使用我的Windows用户名和密码