如何使用Java处理Active Directory过滤器中的重音

时间:2015-08-17 19:07:10

标签: java active-directory

我会尽量保持这个简洁:

我编写了一个允许用户按名称搜索的java webapp。键入名称的一部分,它返回它匹配的所有用户的列表。

 searchFilter = "(&(objectClass=user)(givenName=*" + name + "*))";

我在法国环境中工作,许多名字都有口音,大多数是“é”,但有时候也有其他字母(ö,ï,è等等)。问题是有些人在AD注册,他们的名字有重音,有些人被剥夺了。

即。 :两个用户都叫Éric,一个注册为Éric,另一个注册为Eric。

当name =“Eric”时,只返回没有重音的用户,反之亦然,当name =“Éric”时,只返回带重音的用户。我正在寻找一种行为,其中输入“Eric”或“Éric”将返回所有Éric和Eric结果合并。

我的解决方案不太理想,我正在寻找更可靠的东西,但我找不到任何东西:

searchFilter = "(&(objectClass=user)(givenName=*" + stripAccents(name) + "*))";

public static String stripAccents(String s) 
{
    s = Normalizer.normalize(s, Normalizer.Form.NFD);
    s = s.replaceAll("[\\p{InCombiningDiacriticalMarks}]", ""); //remove all accents
    s = s.replaceAll( "e|i|o", "*" ); //replace e, i ,o with wildcard
    System.out.print( s );
    return s;
}

由于添加了许多通配符,这个解决方案显然给了我比预期更多的结果。

用通配符替换所有重音字母是行不通的,因为搜索“Eric”不会返回“Éric”结果。

1 个答案:

答案 0 :(得分:0)

根据Laune在评论中的想法,我尝试将所有e,i,c更改为通配符*,然后过滤结果。它是这样的:

1)我从用java normalizer输入的名称中删除重音,并将所有e,i,c更改为wilcards

    public static String stripAccents(String s) 
{
    s = Normalizer.normalize(s, Normalizer.Form.NFD);
    s = s.replaceAll("[\\p{InCombiningDiacriticalMarks}]", ""); //remove all accents
    s = s.replaceAll( "(?i)e|i|c", "*" ); //replace e, i ,c with wildcard
    return s;
}

2)我在我的代码中执行搜索:这将为我提供大量不需要的结果,我使用Eric作为示例,因为它包含3个字母。搜索是* r **,正如预期的那样返回太多结果。

searchFilter = "(&(objectClass=user)(givenName=*" + Util.stripAccents(name) +"*))";

3)接下来我通过将每个结果传递给一个函数来过滤结果,该函数根据为搜索输入的初始名称创建动态正则表达式模式(我仍然需要使用java中的regex类测试性能)。对于Eric来说,模式就像是。 [eèéêëÉÈÊËE] r [iïîIÏÎ] [cçCÇ]。。然后我检查在搜索中获得的名称是否与模式逐一匹配并保留那些。 (注意。*之前和之后是因为我想保留像“Frederic”这样的结果。

public static boolean nameRessemble(String initialName, String name){      
    String pattern = initialName.replaceAll( "(?i)e|è|é|ê|ë", "[eèéêëÉÈÊËE]" );
    pattern = pattern.replaceAll( "i|ï|î", "[iïîIÏÎ]" );
    pattern = pattern.replaceAll( "c|ç", "[cçCÇ]" );
    boolean match= name.matches("(?i).*" + pattern +".*");
    return match;

}

当我遍历结果以显示它们时,我只需添加一个条件:

 while ( ne.hasMoreElements() ) {
     if(nameRessemble( name, ne.next().getAttributes.get(NAME_FIELD)) {
         // display 
     }
 }

这就是我现在使用的,我可能会尝试一个函数来制作一个searchFilter,其中包含所有可能的情况,例如我的评论。我昨天做得不好,因为它变得非常混乱。性能还可以(与通常的<1秒相比加载1-3秒,取决于添加的通配符数量)