【问题标题】:How do I run a ldap query using R?如何使用 R 运行 ldap 查询?
【发布时间】:2014-04-01 18:23:24
【问题描述】:

我想针对 LDAP 目录查询员工在部门和组中的分布情况...

类似:“给我一个组所有成员的部门名称”然后使用R进行频率分析,但我找不到任何关于如何连接和运行的示例使用 R 的 LDAP 查询。

RCurl 似乎有某种支持(http://cran.r-project.org/web/packages/RCurl/index.html):

此外,底层实现功能强大且广泛, 支持 FTP/FTPS/TFTP(上传和下载)、SSL/HTTPS、telnet、 dict、ldap,还支持cookies、重定向、身份验证等。

但我不是 R 方面的专家,也无法找到使用 RCurl( 或任何其他 R 库)来执行此操作的单个示例..

现在我正在像这样使用 CURL 来获取组的成员:

curl "ldap://ldap.replaceme.com/o=replaceme.com?memberuid?sub?(cn=group-name)"

这里有人知道如何在 R 中使用 RCurl 做同样的事情吗?

【问题讨论】:

  • 我们需要了解更多有关 LDAP 服务器配置的信息。通过curl -u USERNAME 'ldap://192.168.0.66/CN=Users,DC=training,DC=local\?sAMAccountName?sub?(ObjectClass=*)' 的示例LDAP 查询(来自IBM 示例)。它对您不起作用,因为您需要知道正确的搜索参数。通过RCurl 运行它然后处理结果非常简单,但是如果您应该首先在命令行上从curl 获取查询。
  • 现在我正在检索这样一个组的成员列表:ldapsearch -t -h ldap.replaceme.com -x -b "o=replaceme.com" "(cn=group-name)" memberuid
  • @hrbrmstr 如果你能将我的ldapsearch 翻译成curl,然后用RCurl 翻译成R,那将是我正在寻找的确切答案......
  • 嗨@hrbrmstr 我已将我的ldapsearch 查询翻译成curl...你能告诉我如何使用RCurl 运行它吗?跨度>
  • 我自己已经做过了...但非常感谢您的指导@hrbrmstr :-)

标签: r ldap statistics rcurl ldap-query


【解决方案1】:

自己找到了答案:

首先运行此命令以确保已安装 RCurl(如 http://www.programmingr.com/content/webscraping-using-readlines-and-rcurl/ 中所述):

install.packages("RCurl", dependencies = TRUE)
library("RCurl")

然后是带有 ldap URL 的用户 getURL(如 http://www.ietf.org/rfc/rfc2255.txt 中所述,尽管我在阅读 http://docs.oracle.com/cd/E19396-01/817-7616/ldurl.html 并看到 ldap[s]://hostname:port/base_dn?attributes?scope?filter 之前无法理解):

getURL("ldap://ldap.replaceme.com/o=replaceme.com?memberuid?sub?(cn=group-name)")

【讨论】:

【解决方案2】:

我在此处编写了一个函数来将 ldap 输出解析为数据帧,并使用提供的示例作为参考,让一切顺利进行。

希望对大家有所帮助!

library(RCurl)
library(gtools)

parseldap<-function(url, userpwd=NULL)
{
  ldapraw<-getURL(url, userpwd=userpwd)
  # seperate by two new lines
  ldapraw<-gsub("(DN: .*?)\n", "\\1\n\n", ldapraw)
  ldapsplit<-strsplit(ldapraw, "\n\n")
  ldapsplit<-unlist(ldapsplit)
  # init list and count
  mylist<-list()
  count<-0
  for (ldapline in ldapsplit) {
    # if this is the beginning of the entry
    if(grepl("^DN:", ldapline)) {
      count<-count+1
      # after the first 
      if(count == 2 ) {
        df<-data.frame(mylist)
        mylist<-list()
      }
      if(count > 2) {
        df<-smartbind(df, mylist)
        mylist<-list()
      }
      mylist["DN"] <-gsub("^DN: ", "", ldapline)
    } else {
      linesplit<-unlist(strsplit(ldapline, "\n"))
      if(length(linesplit) > 1) {
        for(line in linesplit) {
          linesplit2<-unlist(strsplit(line, "\t"))
          linesplit2<-unlist(strsplit(linesplit2[2], ": "))
          if(!is.null(unlist(mylist[linesplit2[1]]))) {
            x<-strsplit(unlist(mylist[linesplit2[1]]), "|", fixed=TRUE)

            x<-append(unlist(x), linesplit2[2])
            x<-paste(x, sep="", collapse="|")
            mylist[linesplit2[1]] <- x
          } else {
            mylist[linesplit2[1]] <- linesplit2[2]  
          }
        }
      } else {
        ldaplinesplit<-unlist(strsplit(ldapline, "\t"))
        ldaplinesplit<-unlist(strsplit(ldaplinesplit[2], ": "))
        mylist[ldaplinesplit[1]] <- ldaplinesplit[2]
      }

    }

  }
  if(count == 1 ) {
    df<-data.frame(mylist)
  } else {
    df<-smartbind(df, mylist)
  }
  return(df)
}

【讨论】:

    【解决方案3】:

    我遵循了这个策略:

    1. 运行带有 LDAP 查询的 Perl 脚本,以 JSON 格式将数据写入磁盘。
    2. 用R读入json结构,创建数据框。

    对于第 (1) 步,我使用了这个脚本:

    #use Modern::Perl;
    use strict;
    use warnings;
    use feature 'say';
    use Net::LDAP;
    use JSON;
    chdir("~/git/_my/R_one-offs/R_grabbag");
    my $ldap = Net::LDAP->new( 'ldap.mydomain.de' ) or die "$@";
    my $outfile = "ldapentries_mydomain_ldap.json";
    my $mesg = $ldap->bind ;    # an anonymous bind
    # get all cn's (= all names)
    $mesg = $ldap->search(
                    base   => " ou=People,dc=mydomain,dc=de",
                    filter => "(cn=*)"
                  );
    
    my $json_text = "";
    my @entries;
    
    foreach my $entry ($mesg->entries){
     my %entry;
     foreach my $attr ($entry->attributes) {
        foreach my $value ($entry->get_value($attr)) {
          $entry{$attr} = $value;
        }
      }
      push @entries, \%entry;
    }
    
    $json_text = to_json(\@entries);
    say "Length json_text: " . length($json_text);
    
    
    open(my $FH, ">", $outfile);
    print $FH $json_text;
    close($FH);
    $mesg = $ldap->unbind;
    

    您可能需要检查 ldap 服务器返回的条目的最大大小限制。 见https://serverfault.com/questions/328671/paging-using-ldapsearch

    对于第 (2) 步,我使用了这个 R 代码:

    setwd("~/git/_my/R_one-offs/R_grabbag")
    library(rjson)
    # read into R list, from file, created from perl script
    json <- rjson::fromJSON(file="ldapentries_mydomain_ldap.json",method = "C")
    head(json)
    
    # create a data frame from list
    library(reshape2)
    library(dplyr)
    library(tidyr)
    
    # not really efficient, maybe thre's a better way to do it
    df.ldap <- json %>% melt %>% spread( L2,value)
    
    # optional:
    # turn factors into characters
    i <- sapply(df.ldap, is.factor)
    df.ldap[i] <- lapply(df.ldap[i], as.character)
    

    【讨论】:

      【解决方案4】:

      我编写了一个 R 库,用于使用 openldap 库访问 ldap 服务器。 详细地说,函数searchldap 是openldap 方法searchldap 的包装器。 https://github.com/LukasK13/ldapr

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-28
        • 1970-01-01
        • 2014-11-18
        • 1970-01-01
        • 2015-04-15
        相关资源
        最近更新 更多