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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解析ldap过滤器以转义特殊字符相关的知识,希望对你有一定的参考价值。

ejb服务将ldap过滤器作为字符串,并从ActiveDirectory返回结果。 问题是,有时属性值包含需要为整个过滤器转义的特殊字符,如下所示: https://msdn.microsoft.com/en-us/library/aa746475(v=vs.85).aspx 以及此处指定的专有名称属性值: https://msdn.microsoft.com/en-us/library/aa366101(v=vs.85).aspx 为了实现此目的,服务必须执行以下操作:

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

Java native javax.naming.ldap.Rdn可以逃脱dn值,但不是幂等的。至于其他任务,到目前为止,我一直无法找到一个允许我完成它们的库。 现在我倾向于认为逃避ldap过滤器的工作应该由服务的用户而不是服务本身完成,因为服务很难告诉逃避实际值。此外,在没有经过良好测试的库的情况下解析复杂的字符串(如ldap过滤器)似乎容易出错。 关于如何解决这个问题的任何想法?这个任务可以自动完成吗?

答案

对于转义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("00", "\00");
}

这里要记住的最重要的事情是用替换5C必须先发生,这样你就不会双重逃避任何角色。否则它非常简单;没有任何特殊的技巧需要注意。

我想指出,这是为了逃避LDAP过滤器中的个别值,而不是整个LDAP过滤器。但是,如果您愿意,可以使用该函数来逃避这样的事情,以便搜索:

LdapEscape("(!(sn=m*))"); // 28!28sn=m2A29
另一答案

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;
}

以上是关于解析ldap过滤器以转义特殊字符的主要内容,如果未能解决你的问题,请参考以下文章

在我们将其解析为 JSON 之前,Snowflake 如何转义对象数组字符串中的所有特殊字符?

如何转义xml中的特殊字符

filter过滤器实现特殊字符转义

函数stripslashes去除转义 shopnc 搜索框过滤特殊字符 输入单斜杆会自动转义

如何转义变量中的特殊字符以在 bash 中提供命令行参数

如何转义 YAML 字符串中的冒号和其他特殊字符?