tomcat容器中使用JNDI访问外部openLDAP提供的目录服务
2015-04-20 16:58
351 查看
tomcat容器中使用JNDI访问外部openLDAP提供的目录服务
tomcat容器中使用JNDI访问外部openLDAP提供的目录服务Preface
环境工具
主要参考文档
JNDI调用外部服务基本过程说明
对应修改WebServicejava 为了方便使用ldap的访问直接放在了该类中看起来有些不舒服实际应用中可以单独分开
OpenLDAP 配置过程及文件
Preface
本smaple 使用OpenLDAP 提供目录服务,并使用Berkeley DB 作为backend在之前jerseyRestfulservice&Client的基础上需要进行细微的修改
参考tutorialspoint
本文原创,允许转载但务必贴出本文链接
环境&工具
Jersey JAX-RS 2.0 RI bundle 解压后将所有.jar文件放在WebContent>WEB-INF>lib下面json.jar 注:因为eclipse有特殊的喜好,在web servicejar 工程中,jar包的引用根据web容器而有所不同,对于tomcat,所有引用.jar必须放在web-info/lib/下
OpenLDAP version “openldap-2.4.40”
Berkeley DB version “db-4.7.25”
bdb-dev(4.8)Ubuntu 下可直接使用”sudo apt-get install libdb-dev”(注:bdb的文档中没看到对该包的依赖)
java version “1.8.0_40”
tomcat 8.0
eclipse Luna
mysql 5.6.19
主要参考文档
OpenLDAP Software 2.4 Administrator’s Guide | 中文版相关概念Configure LDAP service in tomcat
stackoverflow
stackexchange
Q&A emails that could be found in OpenLDAP’s host
JNDI调用外部服务基本过程说明
JNDI wikipediaOpenLdap wikipedia
基本概念:
JNDI: Java Naming and Directory Interface
可以由多种方式实现JNDI服务
在server/context.xml 中添加resource,容器会自动添加该外部服务,然后在servlet中lookup()
在serverlet 中手动添加访问配置,通过context factory生成该服务的context,然后在servlet中lookup()
在ejb中注入(injection resource)
ldap及openLDAP:概念颇多,需要参考OpenLDAP Software 2.4 Administrator’s Guide | 中文版相关概念
对应修改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; /* receive GET & POST requests from http://localhost:8080/RestfulService/API/restService */ @Path("/restService") public class WebService { /* receive json data & search in mysql with it */ @POST @Consumes(MediaType.APPLICATION_JSON) public Response json_restResponse(InputStream incomingData) { // json receiving variables String receivedString = ""; JSONObject receivedJson = null; // temp variables // returnCode will be send to client and be present in the console view String returnCode = "SEARCH PROGRESS & RESULTS:"; // receive the json data as receivedJson(JSONObject) try { BufferedReader in = new BufferedReader(new InputStreamReader(incomingData)); String line = null; while ((line = in.readLine()) != null) { receivedString += line; } try { // convert data stream to json receivedJson = new JSONObject(receivedString); 4000 returnCode += "\n\n- receive json data successfully..."; // call jpa method 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(); } /* receive the GET requests & test whether the server is on */ @GET @Produces(MediaType.TEXT_PLAIN) public String sayPlainTextHello() { String returnCode = "this is a test~"; try { ldapSearch(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("ldapSearch error"); } return returnCode; } // Search for the full name of a person whoes uid equals to "fbloggs" // (or we can search for the password for identity recognization) public static String ldapSearch() throws Exception { DirContext ldapContext = null; ldapContext = createLDAPContext(); String returnCode = ""; // Set the filter String uid = "fbloggs"; String filter = "(&(objectClass=inetOrgPerson)(uid=" + uid + "))"; try { // Set the contents that will be shown String[] attrPersonArray = { "uid", "userPassword", "cn", "sn", "mail" }; SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); searchControls.setReturningAttributes(attrPersonArray); // Receive result & print out // NamingEnumeration answer = ldapContext.search("dc=sample,dc=com", filter.toString(), searchControls); 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) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("search & output error"); } // Close the context when we're done closeLDAPContext(ldapContext); return returnCode; } // Create ldapContext public static DirContext createLDAPContext() { // Set up environment for creating initial context 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"); // Authenticate as S. User and password "mysecret" 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 { // Create initial context ldapContext = new InitialDirContext(env); System.out.println(ldapContext.toString()); System.out.println("create ldap context successfully"); } catch (NamingException e) { e.printStackTrace(); } return ldapContext; } // Close ldapContext public static void closeLDAPContext(DirContext ldapContext) { try { ldapContext.close(); } catch (NamingException e) { // TODO Auto-generated catch block 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
相关文章推荐
- 使用JNDI来访问命名服务或者目录服务
- 使用 OpenLDAP 提供集中式网络目录服务
- 配置Tomcat: 设置允许访问服务目录中文件链接
- JNDI目录服务及LDAP服务器使用入门教程
- linux下使用apache http server 连接 tomcat 达到使用直接apache一个服务端口就可访问php和jsp
- JNDI(Java 命名和目录接口)(三)---- Tomcat中配置和使用JNDI
- 操作必须使用一个可更新的查询;HTTP 500 - 内部服务器错误; 您未被授权查看该页;您不具备使用所提供的凭据查看该目录或页的权限;HTTP 错误 401.3 - 访问被资源 ACL 拒绝
- Tomcat 5 servlet/JSP 容器 JNDI 资源使用说明 (一)
- 使用容器提供的数据库连接池--JNDI用法
- 使用JNDI访问Domino目录
- 为什么 FleaPHP 使用 Table Data Gateway 代替 Active Record 来提供数据库访问服务
- 您未被授权查看该页 您不具备使用所提供的凭据查看该目录或页的权限 HTTP 错误 401.1 - 未经授权:访问由于凭据无效被拒绝。
- 为什么 FleaPHP 使用 Table Data Gateway 代替 Active Record 来提供数据库访问服务
- 为什么 FleaPHP 使用 Table Data Gateway 代替 Active Record 来提供数据库访问服务
- 为什么 FleaPHP 使用 Table Data Gateway 代替 Active Record 来提供数据库访问服务
- 为什么 FleaPHP 使用 Table Data Gateway 代替 Active Record 来提供数据库访问服务
- 为什么 FleaPHP 使用 Table Data Gateway 代替 Active Record 来提供数据库访问服务
- 为什么 FleaPHP 使用 Table Data Gateway 代替 Active Record 来提供数据库访问服务
- 为什么 FleaPHP 使用 Table Data Gateway 代替 Active Record 来提供数据库访问服务
- 为什么 FleaPHP 使用 Table Data Gateway 代替 Active Record 来提供数据库访问服务