Gooday,
我对Spring-LDAP有一个相当奇怪的问题,它本质上看起来更像是一个JSNI问题,而不是Spring问题。
问题:
我有以下LDAP结构:
dc=company,dc=com,dc=productname
|-o=TESTORG1
| |-ou=UserGroupName
| |-ou=users
| |-ou=user1@TESTORG1
|-o=TESTORG2
| |-ou=User/Group/Name
| |-ou=users
| |-ou=user1@TESTORG2
所以我可以通过Spring给出的LdapTemplate非常巧妙地创建这个。但是,如果我尝试以递归方式删除组织,我会遇到一些奇怪的问题。
@Test
public void createSimpleOrganisationWithSpecialChars() throws NamingException {
LdapOrganisation originalOrg = new LdapOrganisation("TESTORG2");
LdapUserGroup userGroup = new LdapUserGroup("User/Group/Name");
userGroup.addUser(new User("user1",originalOrg ));
originalOrg.addUserGroup(userGroup);
dataAccess.updateLdap(originalOrg);
OrganisationDao org = new OrganisationDao(this.ldapTemplate);
org.unbind(organisation,true);
}
unbind的实现如下:
public void unbind(LdapOrganisation organisation, boolean recursive) {
if(organisation != null) {
DirContextAdapter context = new DirContextAdapter(buildDn(organisation));
mapToContext(organisation, context);
ldapTemplate.unbind(context.getDn(), recursive);
}
}
现在如果我运行此代码,我会收到以下错误:
org.springframework.ldap.InvalidNameException: Invalid name: "ou=User/Group/Name"; nested exception is javax.naming.InvalidNameException: Invalid name: "ou=User/Group/Name"
at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:136)
at org.springframework.ldap.support.LdapUtils.newLdapName(LdapUtils.java:416)
at org.springframework.ldap.core.LdapTemplate.deleteRecursively(LdapTemplate.java:1103)
at org.springframework.ldap.core.LdapTemplate$25.executeWithContext(LdapTemplate.java:1074)
at org.springframework.ldap.core.LdapTemplate.executeWithContext(LdapTemplate.java:817)
at org.springframework.ldap.core.LdapTemplate.executeReadWrite(LdapTemplate.java:812)
at org.springframework.ldap.core.LdapTemplate.doUnbindRecursively(LdapTemplate.java:1072)
at org.springframework.ldap.core.LdapTemplate.unbind(LdapTemplate.java:1036)
at net.thadir.dataservices.ldap.dao.OrganisationDao.unbind(OrganisationDao.java:108)
at net.thadir.dataservices.ldapaccess.LdapDataAccessTest.cleanTest(LdapDataAccessTest.java:93)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:33)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:239)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: javax.naming.InvalidNameException: Invalid name: "ou=User/Group/Name"
at javax.naming.ldap.Rfc2253Parser.parseAttrType(Rfc2253Parser.java:155)
at javax.naming.ldap.Rfc2253Parser.doParse(Rfc2253Parser.java:108)
at javax.naming.ldap.Rfc2253Parser.parseDn(Rfc2253Parser.java:70)
at javax.naming.ldap.LdapName.parse(LdapName.java:785)
at javax.naming.ldap.LdapName.<init>(LdapName.java:123)
at org.springframework.ldap.support.LdapUtils.newLdapName(LdapUtils.java:414)
... 37 more
现在,如果我只是在测试中进行正常的解除绑定,那么它只是在用户组上进行。没有真正的问题..但实际上这是一个问题。因为看起来Spring用于递归删除了JDNI patern(那比LDAP允许的更严格)和正常的unbinds。它运作得很好。
现在我真的想让我的递归工作开箱即用。我尝试使用以下代码删除组:
在OrganisationDoa:
public void unbind(LdapOrganisation organisation, boolean recursive) {
if(organisation != null) {
UserGroupDao ugu = new UserGroupDao(ldapTemplate);
ugu.delete(organisation);
DirContextAdapter context = new DirContextAdapter(buildDn(organisation));
mapToContext(organisation, context);
ldapTemplate.unbind(context.getDn(), recursive);
}
}
在UserGroupDao中:
public void delete(LdapOrganisation ldapOrganisation, String ldapUserGroup) {
ldapTemplate.unbind(buildDn(ldapOrganisation.getOrganisationShortname(), ldapUserGroup));
}
public void delete(LdapOrganisation ldapOrganisation) {
for (LdapUserGroup userGroup : ldapOrganisation.getUserGroups()) {
delete(ldapOrganisation,userGroup.getGroupName());
}
}
但这似乎不起作用,看到我仍然得到相同的堆栈跟踪(因此尝试在同一个步骤中执行它似乎不起作用)。
我一直在阅读所有这些RFC规范,看起来很旧。并且LDAP似乎只允许它,因为Spring似乎使用JDNI作为递归部分,我得到了这个问题。对预期会损坏的部件进行预清理似乎也无法正常工作。所以我很想听听一些建议/想法如何解决这个问题。
答案 0 :(得分:0)
最后,我必须自己实现org.springframework.ldap.core.LdapTemplate
以解决问题,因为修复程序如下:
package net.thadir.dataservices.ldap.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.NamingException;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.LdapContextSource;
import javax.naming.Binding;
import javax.naming.Name;
import javax.naming.NamingEnumeration;
import javax.naming.directory.DirContext;
import javax.naming.ldap.LdapName;
public class FixedLdapTemplate extends LdapTemplate {
private static final Logger LOGGER = LoggerFactory.getLogger(FixedLdapTemplate.class);
public FixedLdapTemplate(LdapContextSource contextSource) {
super(contextSource);
}
/**
* Delete all subcontexts including the current one recursively.
*
* @param ctx The context to use for deleting.
* @param name The starting point to delete recursively.
* @throws NamingException if any error occurs
*/
@Override
protected void deleteRecursively(DirContext ctx, Name name) {
NamingEnumeration enumeration = null;
try {
enumeration = ctx.listBindings(name);
while (enumeration.hasMore()) {
Binding binding = (Binding) enumeration.next();
String bindingName = binding.getName();
LdapName childName = org.springframework.ldap.support.LdapUtils.newLdapName(fixJDNIBug(bindingName));
childName.addAll(0, name);
deleteRecursively(ctx, childName);
}
ctx.unbind(name);
LOGGER.debug("Entry {} deleted", name);
}
catch (javax.naming.NamingException e) {
throw org.springframework.ldap.support.LdapUtils.convertLdapException(e);
}
finally {
try {
if (enumeration != null) {
enumeration.close();
}
}
catch (Exception e) {
LOGGER.trace("Never mind this", e);
}
}
}
/**
* Becouse somhow JDNI things that if you have a binding with some special characters it adds some extra " to the beginnin and the end. We have to remove it.
*
* @param bindingName
* @return
*/
private static String fixJDNIBug(String bindingName) {
String result = bindingName;
if(result.contains("/") && result.startsWith("\"") && result.endsWith("\"")) {
result = result.substring(1,bindingName.length()-1);
}
return result;
}
}
有问题的bug在过去十年中一直是JDNI的一部分,所以我希望它很快就会在Spring中修复。令我感到遗憾的是,我必须为她们提供一些小课程。