??xml version="1.0" encoding="utf-8" standalone="yes"?>
import java.util.Properties;
import javax.naming.*;
import javax.naming.directory.*;
/*
* Created on 2005-10-26
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
class LdapAuth
{
public static void main(String[] args)
{
//***************** user information to be authenticated ********************************
//*****************Please modify the following three properties accordingly ************
String ldapHost= "ldap://aaa:389"; //ldap host + port number
String DN = "cn=admin,cn=users,dc=aa,dc=com,dc=cn";
String password = "changeit" ;
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
props.put(Context.SECURITY_AUTHENTICATION, "simple"); //use simple authentication mechanism
props.put(Context.SECURITY_PRINCIPAL, DN);
props.put(Context.SECURITY_CREDENTIALS, password);
props.put(Context.PROVIDER_URL, ldapHost);
long start = System.currentTimeMillis();
long end=0;
long time =0;
try
{
System.out.println("authenticating");
DirContext ctx = new InitialDirContext(props);
System.out.println("authenticated");
end = System.currentTimeMillis();
time = end - start;
System.out.println( "authentication takes = " + time + " millis");
System.out.println("successfully authenticate DN: "+DN);
Attributes Atb = ctx.getAttributes("cn=username,ou=it,dc=aa,dc=com,dc=cn");
NamingEnumeration enum = Atb.getAll();
System.out.println("aa");
while (enum.hasMore()) {
Attribute attr = (Attribute)enum.next();
System.out.println(attr);
}
}
catch (Exception ex)
{
end = System.currentTimeMillis();
time = end - start;
System.out.println("Exception is "+ex.toString());
ex.printStackTrace();
System.out.println( "authentication takes = " + time + " millis");
System.out.println("fail to authenticate DN: "+DN);
}
}
}
adauth.java
import java.lang.*; import java.util.Hashtable ; import javax.naming.*; import javax.naming.directory.* ; import javax.naming.ldap.*; import javax.naming.spi.*; public class ADAuth { //環境a定 private Hashtable env = null; //目錄 DirContext ctx = null; //是否能login boolean bLogin = false; //更改是否成功 boolean getAttr = false; public ADAuth(String strId ,String strPassword ){ env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://xxx.xxx.xxx.xxx:389"); env.put(Context.SECURITY_AUTHENTICATION,"Simple"); env.put(Context.SECURITY_PRINCIPAL,"cn="+strId+",cn=users,DC=EEE,DC=abc,DC=com,DC=tw"); env.put(Context.SECURITY_CREDENTIALS , strPassword ); }//end ADAuth() public ADAuth(){ this( "Administrator" , "xxxxxxx" ); } public boolean checkAuth(){ try{ System.out.println("------------------"); System.out.println("連入LDAP--->"); ctx = new InitialDirContext(env); System.out.println("ok"); bLogin = true ; } catch(javax.naming.AuthenticationException authe) { System.out.println("失敗"); bLogin = false ; } catch(Exception e) { System.out.println("失敗"); System.out.println(e); } finally{ try{ ctx.close(); }catch(Exception Ignore){} } return bLogin ; } public boolean getAttribute(String a){ //a定要取得的attribute String[] attrIds ={"displayName"}; try{ ctx = new InitialDirContext(env); Attributes Atb = ctx.getAttributes("cn=users,DC=EEE,DC=abc,DC=com,DC=tw",attrIds); NamingEnumeration enum = Atb.getAll(); while (enum.hasMore()) { Attribute attr = (Attribute)enum.next(); System.out.println(attr); } System.out.println("------------------ok"); getAttr = true; } catch(javax.naming.AuthenticationException authe) { System.out.println("失敗"); getAttr = false; } catch(Exception e) { System.out.println("失敗"); getAttr = false; System.out.println(e); } finally{ try{ ctx.close(); }catch(Exception Ignore){} } return getAttr; } }
LDAP的英文全U是Lightweight Directory Access Protocol,卌量目录讉K协议.我们
知道,Z对计机|络的用和理涉及了各U庞杂的资源,信息.Z提高性能,便于?BR>?有效理分布式应用的服务,资源,用户及别的对象信?q些信息需要清?一致地l?BR>lv?Zq样的需?描述各种用户,应用,文g,打印机和其它可从|络讉K的资源的
信息被集中到一个特D的数据库中,q种数据库被UCؓ目录.目录存放对象的公开或非公开?BR>信息,q些信息以某U顺序组l?描述了每个对象的l节.电话?图书馆藏书卡片目录就?BR>常见的目?
LDAP是基于X.500标准?讉K X.500 目录需要某U协?例如:目录讉K协议 (DAP).
然?DAP 需要大量的pȝ资源和支持机制来处理复杂的协?LDAP 仅通过使用原始 X.500
目录存取协议 (DAP) 的功能子集而减了所需的系l资源消?而且可以Ҏ需要定??BR>?与X.500不同,LDAP支持TCP/IP,q对讉KInternet是必ȝ.
Z能对LDAP协议q行更好的理?我们需要对以下概念有初步的认识:
目录:Directory,存放对象的信?q些信息以某U顺序组l?详细描述每个对象.
目录信息?DIT,Directory Information Tree,目录条目的集合构成了目录信息?
条目:Entry,目录信息树中的一个结?是一个对象信息的集合,是目录信息中最基本?BR>单位,包含该对象的一pd属?
属?Attribute,属性描q对象的特征.一个属性由属性类?type)和一个或多个属性?BR>(values)构成.
相对标识?RDN,Relative Distinguished Name,条目的名?
唯一标识?DN,Distinguished Name,在一个目录信息树中唯一标识一个条目的名字.
LDAPQ轻量目录讉K协议QLightweight Directory Access Protocol)是实现提供被UCؓ目录服务的信息服务?
目录服务是一U特D的数据库系l,其专门针对读取,览和搜索操作进行了特定的优化。目录一般用来包含描
q性的Q基于属性的信息q支持精l复杂的qo能力。目录一般不支持通用数据库针对大量更新操作操作需要的
复杂的事务管理或回卷{略。而目录服务的更新则一般都非常单。这U目录可以存储包括个Z息、web铄?
jpeg囑փ{各U信息。ؓ了访问存储在目录中的信息Q就需要用运行在TCP/IP之上的访问协议—LDAP?
LDAP目录中的信息是是按照树型l构l织Q具体信息存储在条目(entry)的数据结构中。条目相当于关系数据库中
表的记录Q条目是h区别名DNQDistinguished NameQ的属性(AttributeQ,DN是用来引用条目的QDN相当?
关系数据库表中的关键字(Primary KeyQ。属性由cdQTypeQ和一个或多个|ValuesQ组成,相当于关pL
据库中的字段QFieldQ由字段名和数据cdl成Q只是ؓ了方便检索的需要,LDAP中的Type可以有多个ValueQ?
而不是关pL据库中ؓ降低数据的冗余性要求实现的各个域必L不相关的。LDAP中条目的l织一般按照地理位|?
和组l关p进行组l,非常的直观。LDAP把数据存攑֜文g中,为提高效率可以用基于烦引的文g数据库,而不
是关pL据库。类型的一个例子就是mailQ其值将是一个电子邮件地址?
WebLogic的内|的LDAP Server支持IETF LDAP为LDAPv3制定的控制访问模型。下面这个片断将讲述在内|的LDAP
Server中怎样实现控制讉K。可以通过~辑讉K控制文g来将q些规则直接应用到目录的入口?BR>WebLogic中的讉K控制文g是acls.prop。在Server的lib中可以找到这个文件?BR>q个文g的所有访问控制规则都被注释掉了,如果x改这些规则,你要手工更改q个文g?BR>注意QWebLogic Server内置的LDAP Server在默认的情况下只允许Admin帐号讉KQWebLogic Server的security providers
只用Admin帐号讉K内置的LDAP Server。如果你不想使用外部的LDAP Brower讉KWebLogic Server的内|的LDAP ServerQ?BR>或者你只想使用Admin帐号讉K内置的LDAP ServerQ你不需要编辑acls.prop文gQ?BR>讉K控制文gQThe Access Control FileQ?/P>
讉K控制文gQacls.propQ包含内|的LDAP Server的整个目录的完整的访问控制列表(ACLQ?BR>q个文g中的每一行都包含一个访问控制规则。一个访问控制规则由下面接个部分l成Q?BR> 讉K控制位置(Access Control Location)
每个讉K控制规则都应用于LDAP目录中的一个给定的位置。这个位|通常是一个区别命名(DNQ,但有一个例外,q就是[root]Q如果访问控制规则应用到整个目录Q则只需要指定位|ؓ[root]可以了Q?BR> 如果被访问或更改的入口的位置与访问控制规则指定的位置不相{,或在讉K控制规则指定的位|的下Q则q个讉K控制规则不会被执行?/P>
讉K控制范围QAccess Control ScopeQ?BR> 讉K控制范围?U:
Entry-一个Entry范围的访问控制列表只在下面的情况下被执行Q?BR> LDAP目录的入口的DN与访问控制规则指定的位置相同。这L规则对于包含了比q行和副入口更敏感信息的单独入口非常有用?BR> Subtree-意味着讉K控制规则指定的位|及子树都可以适用q条规则?BR> 如果Entry与Subtree在访问控制规则中有冲H,则Entry要优先于Subtree?/P>
讉K权限QAccess RightsQ?BR> 讉K权限应用于整个对象或对象的属性,?个|grantQ准许)或denyQ拒l)。访问权限指定了LDAP操作的类型?BR>
许可(grant或deny)
应用规则的属?attribute)
允许或拒l访问的主题(subject)
在weblogic可以~写E序来访问LDAP.上手时可以选择JXplorer工具?BR> 1.LDAP Server及LDAP BrowserQ?BR> 对于WLS LDAP为理解v来简单,L限制的方法是修改bea\weblogic81\server\lib\acls.prop文g后。修Ҏ法:
在该文g最后添加以下几行?BR>[root]|entry#grant:s,r,o,w,c,m#[all]#public
[root]|subtree#grant:s,r,o,w,c,m#[all]#public:
[root]|subtree#grant:a,d,e,i,n,b,t#[entry]#public:
cn=schema|entry#grant:s,r,o,w,c,m#[all]#public:
cn=schema|entry#grant:a,d,e,i,n,b,t#[entry]#public:
注意Q该文g中这些行之间Q以及其他行之间不能有空行,否则启动WLS会报错的。修改好之后可以启动WLS了,
启动后进入Console里修改Ldap Server的密码。密码修改完后需要再重新启动一ơWLS?BR>LDAP刚上手的时候没有方便的工具会很费劲。我看了CSDN上“兔八哥”的文章Q用JXplorerQ感觉很不错?BR>想看q篇文章Q到CSDN上搜一下“兔八哥”,pd中No.12是关于JXplorer的配|和使用。我的连接参数如下:
Host:localhost//Ҏ实际修改
Port:7001
Protocol:LDAP v3
Base DN:dc=ldapdomain//Ҏ实际修改
Level:User+Password
User DN:cn=Admin
Password:weblogic//Ҏ实际修改
.~程操作LDAP Server?BR> 下面四个JAVAҎQ分别用于初始化Q查询,dQ删除,修改Q关闭连接?BR> 记得每次都需要先大概q接Q操作,然后关闭q接。和使用数据库差不多?BR>
首先是需要用到的头文Ӟ
import java.util.Hashtable;
import java.util.Enumeration;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls ;
import javax.naming.NamingEnumeration;
import javax.naming.directory.SearchResult;
import javax.naming.directory.Attributes ;
import javax.naming.directory.Attribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.ModificationItem;
import java.lang.reflect.Method;
import java.io.BufferedReader;
import java.io.InputStreamReader;
然后是一个类域,用于保存上下文:
DirContext ctx = null;
然后是初始化Q?BR>
public void init(){
String account="Admin";//操作LDAP的帐戗默认就是Admin?BR> String password="weblogic";//帐户Admin的密码?BR> String root="dc=ldapdomain"; //所操作的WLS域。也是LDAP的根节点的DC
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");//必须q样写,无论用什么LDAP服务器?BR> env.put(Context.PROVIDER_URL, "ldap://localhost:7001/" + root);//LDAP服务器的地址:端口。对WLS端口是7001
env.put(Context.SECURITY_AUTHENTICATION, "none");//授权界别Q可以有三种授权U别Q但是如果设为另外两U都无法dQ我也不知道为啥Q但是只能设成这个?none"?BR> env.put(Context.SECURITY_PRINCIPAL, "cn=" + account + "," + root);//载入登陆帐户和登录密?BR> env.put(Context.SECURITY_CREDENTIALS, password);
try{
ctx = new InitialDirContext(env);//初始化上下文
System.out.println("认证成功");//q里可以Ҏ异常抛出?BR> }catch(javax.naming.AuthenticationException e){
System.out.println("认证p|");
}catch(Exception e){
System.out.println("认证出错Q?+e);
}
}
查询操作Q?BR>
public void search(){//我只能按照某些属性查找节点,偶还不会怎么查找一个目录或按照更复杂的正则式查扄定节点/目录
try{
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
System.out.print("what would you want to search:");
BufferedReader bd=new BufferedReader(new InputStreamReader(System.in));
String s=bd.readLine();
NamingEnumeration en = ctx.search("", "uid="+s, constraints); //要查询的UID。如果是*则可以查到所有UID的节?BR> if(en == null){
System.out.println("Have no NamingEnumeration.");
}
if(!en.hasMoreElements()){
System.out.println("Have no element.");
}
while (en != null && en.hasMoreElements()){//可以查出多个元素
Object obj = en.nextElement();
if(obj instanceof SearchResult){
SearchResult si = (SearchResult) obj;
System.out.println("\tname: " + si.getName());
Attributes attrs = si.getAttributes();
if (attrs == null){
System.out.println("\tNo attributes");
}else{
for (NamingEnumeration ae = attrs.getAll(); ae.hasMoreElements();){//获得该节点的所有属?BR> Attribute attr = (Attribute) ae.next();//下一属?BR> String attrId = attr.getID();//获得该属性的属性名
for (Enumeration vals = attr.getAll();vals.hasMoreElements();){//获得一个属性中的所有属性?BR> System.out.print("\t\t"+attrId + ": ");
Object o = vals.nextElement();//下一属性?BR> if(o instanceof byte[])
System.out.println(new String((byte[])o));
else
System.out.println(o);
}
}
}
}
else{
System.out.println(obj);
}
System.out.println();
}
}catch(Exception e){
System.out.println("Exception in search():"+e);
}
}
d操作Q?BR>
public void add(){
try{
String newUserName = "stella";
BasicAttributes attrs = new BasicAttributes();
BasicAttribute objclassSet = new BasicAttribute("objectclass");
objclassSet.add("person");
objclassSet.add("top");
objclassSet.add("organizationalPerson");
objclassSet.add("inetOrgPerson");
objclassSet.add("wlsUser");
attrs.put(objclassSet);
attrs.put("sn", newUserName);
attrs.put("uid", newUserName);
attrs.put("cn", newUserName);
ctx.createSubcontext("uid=" + newUserName+",ou=people,ou=myrealm", attrs); //d一个节点,我还不会d目录
}catch(Exception e){
System.out.println("Exception in add():"+e);
}
}
修改操作Q?BR>
public void edit(){
try{
String account = "stella";//修改以前旧的?BR> String sn = "stella sn";//修改以后新的?BR> ModificationItem modificationItem[] = new ModificationItem[1];
modificationItem[0] =
new ModificationItem(
DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("sn", sn));//所修改的属?BR> ctx.modifyAttributes("uid=" + account, modificationItem); //执行修改操作
}catch(Exception e){
System.out.println("Exception in edit():"+e);
}
}
删除节点操作Q?BR>
public void delete(){
try{
String uid = "stella";
ctx.destroySubcontext("uid=" + uid); //按照UID删除某个节点。我q不会删除一个目录?BR> }catch(Exception e){
System.out.println("Exception in edit():"+e);
}
}
关闭q接Q?BR>
public void close(){
if(ctx != null)
{
try
{
ctx.close();
}
catch (NamingException e)
{
System.out.println("NamingException in close():"+e);
}
}
}
我对LDAP的理解:它是用于对资源的理和服务的讉K协议Q在Weblogicq_上的JNDIQ包含EJB和DataSource)都是提供它来提供的?BR>正是JNDI的服务和RMIl合Ş成J2EEq_上分布式的应用,因此说到底层Q还是LDAP协议的支持?/P>
完成認證後,可透過建立?目錄服務 物g擷取更多?LDAP 目錄a息Q不過目前還在測試中...
package test;import javax.naming.*; import javax.naming.directory.*;
import java.util.Hashtable;
/** * 建立一個透過 ActiveDirectory 認證過的使用者物? * * @author Ada */ public class ADAuth {
/** * @return 認證是否通過 */ publicstaticboolean login( String email, String password ) {
/** LDAP 環境變數 */ Hashtable env = null;
/** 目錄 */ DirContext ctx = null;
/** 認證狀?*/ boolean logged = true;
env = new Hashtable(); env.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); // a得修改 ActiveDirectory 實際提供L位址 env.put( Context.PROVIDER_URL, "ldap://active.directory.server:389"); // 使用 username + password 進行認證 env.put( Context.SECURITY_AUTHENTICATION, "simple" ); // 使用者的完整 email Q也是 AD 中的 ${sAMAccountName}@your.domain.name env.put( Context.SECURITY_PRINCIPAL, email ); // 認證當時的密? env.put( Context.SECURITY_CREDENTIALS, password );
try { // 若可建立目錄物gQ即表示完成d ctx = new InitialDirContext( env ); logged = true; } catch( AuthenticationException authe ) { // 授權失敗 logged = false; System.out.println( authe ); } catch( Exception e ) { // 不明錯誤 System.out.println( e ); } finally { try { // a得把目錄關? ctx.close(); } catch ( Exception Ignore ) { } }
return logged; }
/** * d行程? * @author Ada */ publicstatic void main( String[] args ) {
// 一定要 email + 密碼才能d if( args.length == 2 ) { System.out.println( "is Logon? : " + login( args[0], args[1] ); } else { System.out.println( "EMail/Password not initialed!" ); } } }
另一?
/*
* ADAuth.java
*
* Created on 2004q??9? 上午 11:37
*/
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.AuthenticationException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
/**
*
* @author ajax
*/
public class ADAuth {
DirContext ctx = null;
Hashtable env = null;
/** Creates a new instance of ADAuth */
public ADAuth(String acct,String password) {
env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
/*
* Ldap://後可接active directory的server名稱或ip,port可以不用key,預設?89
*/
env.put(Context.PROVIDER_URL,"Ldap://192.168.1.16:389");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
/*
* 公司E域為 company.com.tw
*
* 所以有這一D DC=company,DC=com,DC=tw
*/
env.put(Context.SECURITY_PRINCIPAL,"cn="+acct+",cn=users,DC=公司AD的網域名");//,DC=com,DC=tw");
env.put(Context.SECURITY_CREDENTIALS,password);
try{
ctx = new InitialDirContext(env);
System.out.println("驗証通過");
}catch(AuthenticationException authe){
System.out.println("驗証失敗");
}catch(Exception e){
System.out.println(e);
}finally{
try{
ctx.close();
}catch(Exception Ignore){}
}
}
public static void main(String[] args){
new ADAuth("希","密碼");
}
}