解析ldap过滤器以转义特殊字符

Rob*_*rov 5 java regex parsing ldap active-directory

ejb服务将ldap筛选器作为字符串,并从ActiveDirectory返回结果。

问题在于,有时属性值包含特殊字符,需要按此处指定的方式对整个筛选器进行转义:
https : //msdn.microsoft.com/zh-cn/library/aa746475(v=vs.85).aspx
和此处指定的专有名称attibute值:
https ://msdn.microsoft.com/zh-cn/library/aa366101( v= vs.85).aspx
为了完成此操作,该服务必须执行以下操作:

  1. 分析字符串中的dn值,将其分开,并根据dn转义规则对它们进行转义(如果尚未转义)。
  2. 在字符串的其余部分中搜索属性值中的特殊字符,如果尚未转义,请按照常规过滤器转义规则对它们进行转义。
  3. 将结果合并为新的转义过滤器,然后继续传递。

Java本机可以javax.naming.ldap.Rdn转义dn值,但不是幂等的。至于其他任务,到目前为止,我还找不到能够让我完成这些任务的库。

现在,我倾向于认为转义ldap过滤器的工作应该由服务的用户完成,而不是由服务本身完成,因为服务很难区分实际值。另外,对一个复杂的字符串(例如ldap过滤器)进行解析而没有经过良好测试的库在我看来也很容易出错。

关于如何解决这个问题的任何想法?这项任务可以完全自动化吗?

Plu*_*uto 5

对于转义 LDAP 过滤器,我依靠此页面编写以下代码:http : //social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx#Special_Characters

String LdapEscape(String ldap)
{
    if(ldap == null) return "";
    return ldap.replace("\\", "\\5C").replace("*", "\\2A").replace("(", "\\28").replace(")", "\\29").replace("\000", "\\00");
}
Run Code Online (Sandbox Code Playgroud)

这里要记住的最重要的事情是必须先替换\with,\5C这样您就不会双重转义任何字符。否则它非常简单;没有任何需要注意的特殊技巧。

我想指出,这是为了转义放置在 LDAP 过滤器中的单个值,而不是整个 LDAP 过滤器。但是,如果您愿意,可以使用该函数来转义这样的内容,以便可以搜索:

LdapEscape("(!(sn=m*))"); // \28!\28sn=m\2A\29
Run Code Online (Sandbox Code Playgroud)


Chr*_*cki 5

Pluto 的答案非常简洁,但非 ASCII UTF-8 字符(例如 é、á、ö 等)也需要特殊处理。这是我的详细解决方案。

/** 
 * Filter components need to escape special chars.
 * Note that each piece of the filter needs to be escaped, 
 * not the whole filter expression, for example:
 * 
 * "(&(cn="+ esc("Admins") +")(member="+ esc("CN=Doe\\, Jöhn,OU=ImPeople,DC=ds,DC=augur,DC=com") +"))"
 * 
 * @see Oracle Directory Server Enterprise Edition 11g Reference doc
 * @see http://docs.oracle.com/cd/E29127_01/doc.111170/e28969/ds-ldif-search-filters.htm#gdxoy
 * @param s A String field within the search expression
 * @return The escaped string, safe for use in the search expression.
 */
public static String esc(String s)
{
    if(s == null) return "";
    StringBuilder sb = new StringBuilder(s.length());
    for (byte c : s.getBytes(StandardCharsets.UTF_8))
    {
        if (c=='\\') { sb.append("\\5c"); }
        else if (c=='*') { sb.append("\\2a"); }
        else if (c=='(') { sb.append("\\28"); }
        else if (c==')') { sb.append("\\29"); }
        else if (c==0) { sb.append("\\00"); }
        else if ((c&0xff)>127) { sb.append("\\").append(to2CharHexString((c&0xff))); } // UTF-8's non-7-bit characters, e.g. é, á, etc...
        else { sb.append((char)c); }
    }
    return sb.toString();
}

/** 
 * @return The least significant 16 bits as a two-character hex string, 
 * padded by a leading '0' if necessary.
 */
public static String to2CharHexString(int i)
{
    String s = Integer.toHexString(i & 0xff);
    if (s.length()==1) return "0"+s;
    else return s;
}
Run Code Online (Sandbox Code Playgroud)

  • 根据此站点,不需要转义正斜杠:https://social.technet.microsoft.com/wiki/contents/articles/5312.active-directory-characters-to-escape.aspx#LDAP_Filters (2认同)
  • 是的...如果您滚动到我发送的链接的顶部,请查看“Active Directory”和“ADSI”部分。它们解释了 DN 需要转义的内容,并且仅当您使用 ADSI 接口时才需要转义正斜杠。(为了安全起见,如果你逃跑太多,希望它不会受到伤害。)我发布的代码仅用于转义过滤器中使用的字符,而不是 DN。(咆哮:恕我直言,所有这些不同的转义规则都意味着一个脆弱的协议设计,但现在为时已晚。) (2认同)