tomcat容器中使用JNDI访问外部openLDAP提供的目录服务
Preface
- 本smaple 使用OpenLDAP 提供目录服务,并使用Berkeley DB 作为backend
- 在之前jerseyRestfulservice&Client的基础上需要进行细微的修改
- 参考tutorialspoint
- 本文原创,允许转载但务必贴出本文链接
环境&工具
主要参考文档
JNDI调用外部服务基本过程说明
对应修改WebService.java (为了方便使用,ldap的访问直接放在了该类中,看起来有些不舒服,实际应用中可以单独分开)
package webService;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.LdapContext;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Hashtable;
import java.util.List;
@Path("/restService")
public class WebService {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response json_restResponse(InputStream incomingData) {
String receivedString = "";
JSONObject receivedJson = null;
String returnCode = "SEARCH PROGRESS & RESULTS:";
try {
BufferedReader in = new BufferedReader(new InputStreamReader(incomingData));
String line = null;
while ((line = in.readLine()) != null) {
receivedString += line;
}
try {
receivedJson = new JSONObject(receivedString);
returnCode += "\n\n- receive json data successfully...";
List<String> title = JpaHandle.getTitle();
System.out.println(receivedJson.toString());
for(String e:title) {
returnCode += ("\n\ntitle:\t" + e);
if (e == receivedJson.getString("title")) {
returnCode += "\t-that's it!";
} else {
returnCode += ("\t-not the one I'm finding..." + e);
}
}
} catch (JSONException e){
System.out.println(e);
}
} catch (Exception e) {
System.out.println(e);
}
return Response.status(200).entity(returnCode).build();
}
@GET
@Produces(MediaType.TEXT_PLAIN)
public String sayPlainTextHello() {
String returnCode = "this is a test~";
try {
ldapSearch();
} catch (Exception e) {
e.printStackTrace();
System.out.println("ldapSearch error");
}
return returnCode;
}
public static String ldapSearch() throws Exception {
DirContext ldapContext = null;
ldapContext = createLDAPContext();
String returnCode = "";
String uid = "fbloggs";
String filter = "(&(objectClass=inetOrgPerson)(uid=" + uid + "))";
try {
String[] attrPersonArray = { "uid", "userPassword", "cn", "sn", "mail" };
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchControls.setReturningAttributes(attrPersonArray);
NamingEnumeration answer = ldapContext.search("", filter.toString(), searchControls);
StringBuffer sb = new StringBuffer();
while (answer.hasMore()) {
SearchResult result = (SearchResult) answer.next();
Attributes attrs = result.getAttributes();
if (answer.hasMore()){
sb.append(attrs.get("cn").toString().substring(4) + ",");
}
else{
sb.append(attrs.get("cn").toString().substring(4));
}
}
returnCode += sb.toString();
System.out.println("before-");
System.out.println(returnCode);
System.out.println("-after");
}catch(Exception e) {
e.printStackTrace();
System.out.println("search & output error");
}
closeLDAPContext(ldapContext);
return returnCode;
}
public static DirContext createLDAPContext() {
Hashtable env = new Hashtable(11);
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389/dc=sample,dc=com");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=Manager,dc=sample,dc=com");
env.put(Context.SECURITY_CREDENTIALS, "secret");
DirContext ldapContext = null;
try {
ldapContext = new InitialDirContext(env);
System.out.println(ldapContext.toString());
System.out.println("create ldap context successfully");
} catch (NamingException e) {
e.printStackTrace();
}
return ldapContext;
}
public static void closeLDAPContext(DirContext ldapContext) {
try {
ldapContext.close();
} catch (NamingException e) {
e.printStackTrace();
}
}
}
OpenLDAP 配置过程及文件
- 安装Berkeley DB
- 现在对bdb的支持不算很好,可以选择其他方案
- 添加bdb-dev包
- cd build_unix
- ../dist/configure
- make
- make install
- 环境变量的设置:
- env CPPFLAGS=”-I/usr/local/BerkeleyDB.4.7/include” LDFLAGS=”-L/usr/local/BerkeleyDB.4.7/lib”
- 安装OpenLDAP
- 文档中有openLDAP的安装步骤,不过看网上讨论以及亲自实践,还是要准备好不断调试的心情。
- 以下是从各个帖子中搜集到的测试手段(或者也可直接翻api):
- 查看bdb中的现有目录:ldapsearch -x -b ” -s base ‘(objectclass=*)’ namingContexts
- 尝试添加目录(测试manager登录):ldapadd -x -D ‘cn=Manager,dc=localhost,dc=com’ -W
- 测试配置文件正确性:sudo slaptest
- 以debug模式启动slapd:sudo slapd -d 256(通过JNDI使用slapd的时候也可以从这里看到输出)
- 其他的一些tips:
- ./configure –prefix=/usr/local/openldap –enable-bdb=yes 配置时可以随便选prefix路径,但最好还是加上enable-bdb(虽然默认会enable该backend,但最好还是显式配置)
- prefix路径并不是配置的路径,配置文件会在/etc/ldap/下,并且install之后需要rm -rf /etc/ldap/slapd.d/*来删除ldap给的example,不然之后不会被新配置覆盖的
- 配置文件slapd.conf中的配置项前不可有空格,配置项和值之间最好使用tab
- slaptest -f /etc/ldap/slapd.conf -F /etc/ldap/slapd.d 将自己的配置文件slapds.conf生成对应格式的真正配置文件
- 因为很多都是手动修改生成的文件,所以很多文件的所有人和所有组都不是openldap,相关文件访问权限需要修改
- 配置文件及一个从bdb读出的sample