配置信息config.xml
<pre name="code" class="java">Conf>
<ADinformation>
<ADldapHost>ldap://11.241.14.333:389</ADldapHost>
<ADDN>CN=AAA,OU=BBB,OU=CCC,DC=DDD,DC=EEE</ADDN>
<ADpassword>ZXC</ADpassword>
<ADsearchBaseDN>ou=CCC,dc=DDD,dc=com</ADsearchBaseDN>
</ADinformation>
</Conf>
一初始化:
import java.util.Map;
import java.util.Properties;
import javax.naming.Context;
import play.mvc.Controller;
/**
* This class is used to return informations for an AD connection.
* 初始化
*
**/
public class ADconnect {
public static Properties getProps()throws Exception{
try{
Map<String, String> map = Readxml.getXmlInfo("config.xml");
String ldapHost=map.get("ADldapHost");
String DN=map.get("ADDN");
String password=map.get("ADpassword");
String searchBaseDN=map.get("ADsearchBaseDN");
Properties props=new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
props.put(Context.PROVIDER_URL, ldapHost);
props.put("java.naming.ldap.version", "3");
props.put(Context.SECURITY_PRINCIPAL, DN);
props.put(Context.SECURITY_CREDENTIALS, password);
props.put("ADsearchBaseDN", searchBaseDN);
props.put(Context.REFERRAL,"follow");
return props;
}catch(Exception ex)
{
throw ex;
}
}
}
</pre><pre code_snippet_id="363364" snippet_file_name="blog_20140526_22_5959525" name="code" class="java">
二:在AD环境中认证账户信息
import java.util.Map;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import org.xml.sax.SAXException;
/**
* This class is used to authenticate or check informations for an account.
**/
public class ADauthenticate extends Controller {
public static Boolean checkByPassword(String password)
throws NamingException, SAXException, IOException {
Map<String, String> map = Readxml.getXmlInfo("config.xml");
String DistinguishedName = "";
Object obj = Cache.get("DistinguishedName");
if (obj != null) {
DistinguishedName = obj.toString();
} else {
DistinguishedName = session("DistinguishedName");
}
String DN = DistinguishedName;
String url = map.get("ADldapHost");
// get DirContext for AD connect
Properties props = new Properties();
DirContext ctx;
props.put(Context.SECURITY_AUTHENTICATION, "simple");
props.put(Context.SECURITY_PRINCIPAL, DN);
props.put(Context.SECURITY_CREDENTIALS, password);
props.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
props.put(Context.PROVIDER_URL, url);
try {
ctx = new InitialDirContext(props);
ctx.close();
//if return true, this account has successfully login.
return true;
} catch (NamingException err) {
//else, it failed to login.
return false;
}
}
/**
* This function is used to check informations of an account.
*/
</pre><pre code_snippet_id="363364" snippet_file_name="blog_20140526_10_8218727" name="code" class="java">//将用户的各个属性以变量形式声明在类Authbean里
public static Boolean checkInfo(Authbean Info)
throws Exception {
try {
ADsearch ad = new ADsearch();
String answer = ad.searchResult(session("AccountID"),
(ADsearch.searchForWhat.S_ANSWER));
if (!Info.answer.equals(answer)) {
//got wrong informations.
return false;
}
}catch(Exception ex)
{
throw ex;
}
//information matches that in AD.
return true;
}
}
</pre>三:AD修改关键代码<pre>
<pre name="code" class="java">
public class ADmodify {
public enum modifyWhat{
M_LOCK,
M_UNLOCK,
M_UNLOCK2,
M_QUESTION, //问题
M_ANSWER, //回答
}
/**
* This function is used to do simple AD modifies
*/
public static void modifyAccount(modifyWhat What,String content) throws Exception{
Properties props = null;
try {
ADsearch ad=new ADsearch();
int i;
props = ADconnect.getProps();
ModificationItem[] mods = new ModificationItem[1];
Attribute attr2Change = null;
boolean flg=false;
switch(What){
case M_LOCK:
i=Integer.parseInt(ad.searchResult(String.valueOf(Cache.get("AccountID")), ADsearch.searchForWhat.S_USERACCOUNTCONTROL));
attr2Change = new BasicAttribute("userAccountControl", String.valueOf(i|2));
break;
case M_UNLOCK:
i=Integer.parseInt(ad.searchResult(String.valueOf(Cache.get("AccountID")), ADsearch.searchForWhat.S_USERACCOUNTCONTROL));
if(i%4!=0){
attr2Change = new BasicAttribute("userAccountControl", String.valueOf(i-2));
}
else{
attr2Change = new BasicAttribute("userAccountControl", String.valueOf(i));
}
flg=true;
break;
case M_UNLOCK2:
attr2Change=new BasicAttribute("lockoutTime","0");
break;
case M_QUESTION:
attr2Change = new BasicAttribute("extensionAttribute1", content);
break;
case M_ANSWER:
attr2Change = new BasicAttribute("extensionAttribute2", content);
break;
default:
break;
}
DirContext ctx = new InitialDirContext(props);
mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr2Change);
String DistinguishedName = "";
Object obj = Cache.get("DistinguishedName");
if (obj != null){
DistinguishedName = obj.toString();
}else{
DistinguishedName = session("DistinguishedName");
}
ctx.modifyAttributes(DistinguishedName, mods);
if(flg){
modifyAccount(modifyWhat.M_UNLOCK2,"");
flg=false;
}
}catch(Exception ex){
throw ex;
}
}
};
</pre><pre code_snippet_id="363364" snippet_file_name="blog_20140526_14_6222669" name="code" class="java">四:AD 查找
<pre name="code" class="java">import java.util.Enumeration;
import java.util.Properties;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
/**
* This class is used to search account informations
**/
public class ADsearch {
public String searchType="person";
public String searchAttr="sAMAccountName";
public enum searchForWhat{
S_EXIST,
S_LOCKED,
S_INITIAL,
S_DISTINGUISHEDNAME,
S_QUESTION,
S_ANSWER,
S_USERACCOUNTCONTROL,
};
/**
* return a search result value according to the needs.
* @param searchTxt
* search text
* @param What
* attribute to search for
* @return String
* search result values
* @throws Exception
*/
public String searchResult(String searchTxt,searchForWhat What)
throws Exception{
Properties props= ADconnect.getProps();
String result="";
try{
DirContext ctx = new InitialDirContext(props);
String searchFilter;
searchFilter = "(&(objectClass="+searchType+")("+searchAttr+"="+ searchTxt+"))";
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration<?> searchResultEnum = ctx.search(props.getProperty("ADsearchBaseDN"),searchFilter,searchControls);
//switch Search Functions
switch (What){
case S_EXIST:
result=existSearch(searchResultEnum,ctx);
break;
case S_LOCKED:
result=lockedSearch(searchResultEnum,ctx);
break;
case S_INITIAL:
result=initialSearch(searchResultEnum,ctx);
break;
case S_DISTINGUISHEDNAME:
result=otherSearch("distinguishedName",searchResultEnum,ctx);
break;
case S_QUESTION:
result=otherSearch("extensionAttribute1",searchResultEnum,ctx);
break;
case S_ANSWER:
result=otherSearch("extensionAttribute2",searchResultEnum,ctx);
break;
case S_USERACCOUNTCONTROL:
result=otherSearch("userAccountControl",searchResultEnum,ctx);
break;
default:
break;
}
//end of the switched function
}catch(Exception ex){
throw ex;
}
return result;
}
/**
* Decide whether this id exists
*/
private String existSearch(NamingEnumeration<?> searchResultEnum,DirContext ctx)
throws NamingException {
try {
if(searchResultEnum.hasMore()){
//id exists.
return "true";
}
//id non-exists.
return "false";
} catch(NamingException ex){
throw ex;
}
}
/**
* Decide whether this id is locked.
* @return String
* "true" represents "locked" while "false" represents "unlocked"
* @throws NamingException
*/
private String lockedSearch(NamingEnumeration<?> searchResultEnum,DirContext ctx)
throws NamingException {
try {
if(searchResultEnum.hasMore()){
SearchResult searchResult = (SearchResult) searchResultEnum.next();
NamingEnumeration<?> names = searchResult.getAttributes().getAll();
while(names.hasMore()){
Attribute attr=(Attribute)names.nextElement();
//decide whether this id is active or not
if(attr.getID().equals("lockoutTime")){
Enumeration<?> attrValEnum=attr.getAll();
if (attrValEnum.hasMoreElements()) {
String elem = (String) attrValEnum.nextElement();
if(elem!=null && !elem.equals("0")){
//if return true, this account is locked.
return "true";
}
}
}
}
}
//else, this account is not locked.
return "false";
} catch(NamingException ex){
throw ex;
}
}
/**
* Decide whether this id is the first time to login.
*/
private String initialSearch(NamingEnumeration<?> searchResultEnum,DirContext ctx)
throws NamingException{
try {
if(searchResultEnum.hasMore()){
SearchResult searchResult = (SearchResult) searchResultEnum.next();
NamingEnumeration<?> names = searchResult.getAttributes().getAll();
while(names.hasMore()){
Attribute attr=(Attribute)names.nextElement();
if(attr.getID().equals("otherMobile"))
return "false";
}
}
return "true"; //id first login
} catch(NamingException ex){
throw ex;
}
}
/**
* Return an attribute value of a user.
*/
private String otherSearch(String search,NamingEnumeration<?> searchResultEnum,DirContext ctx)
throws NamingException{
try {
String result="";
if(searchResultEnum.hasMore()){
SearchResult searchResult = (SearchResult) searchResultEnum.next();
NamingEnumeration<?> names = searchResult.getAttributes().getAll();
while(names.hasMore()){
Attribute attr=(Attribute)names.nextElement();
if(attr.getID().equals(search)){
Enumeration<?> attrValEnum=attr.getAll();
if (attrValEnum.hasMoreElements()) {
result = (String)attrValEnum.nextElement();
}
}
}
}
return result;
} catch(NamingException ex){
throw ex;
}
}
}
</pre><pre code_snippet_id="363364" snippet_file_name="blog_20140526_17_9036160" name="code" class="java">五:AD账户密码重置
<pre name="code" class="java">//This class is used to reset password for an account.
public class ADresetpwd {
public LdapContext ctx = null;
/**
* This function is used to reset password for an account.
*/
public boolean resetPassword(String distinguishedName,String newPassword){
try{
initial_Ldap();
mod_Pwd(distinguishedName,newPassword);
close_Ldap();
}catch(Exception e){
e.printStackTrace();
//if return false, this action has failed.
return false;
}
//if return true, password has been reset successfully.
return true;
}
/**
* This function is used to connect AD using the security mode.
*
* @throws Exception
*/
private void initial_Ldap() throws Exception {
System.setProperty("javax.net.ssl.trustStore", Utils.keystore);
System.setProperty("javax.net.ssl.trustStorePassword", Utils.keyPassword);
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, Utils.adminName);
env.put(Context.SECURITY_CREDENTIALS, Utils.adminpassword);
env.put(Context.SECURITY_PROTOCOL, "ssl");
env.put(Context.PROVIDER_URL, Utils.ldapURL);
try {
ctx = new InitialLdapContext(env, null);
} catch (NamingException e) {
e.printStackTrace();
throw e;
}
}
</pre><pre code_snippet_id="363364" snippet_file_name="blog_20140526_20_3037349" name="code" class="java"><span style="white-space:pre"> </span>//class Utils
<span style="white-space:pre"> </span>//public static final String adminName = "ssss@silver.com";
<span style="white-space:pre"> </span>//public static final String adminpassword = "mmmmm";
<span style="white-space:pre"> </span>//public static final String keystore = "c:/silverca.keystore";
<span style="white-space:pre"> </span>//public static final String keyPassword = "silver";
<span style="white-space:pre"> </span>//public static final String ldapURL ="ldaps://11.55.222.333:444";
/**
* This function is used to modify password for an account.
*/
private void mod_Pwd(String username, String password) throws UnsupportedEncodingException, NamingException {
ModificationItem[] mods = new ModificationItem[1];
String newQuotedPassword = "\"" + password + "\"";
try {
byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");
mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("unicodePwd", newUnicodePassword));
ctx.modifyAttributes(username, mods);
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
throw e1;
} catch (NamingException e2) {
e2.printStackTrace();
throw e2;
}
}
/**
* This function is to close an AD connection.
*
* @throws NamingException
*/
private void close_Ldap() throws NamingException{
try {
ctx.close();
} catch (NamingException e) {
e.printStackTrace();
throw e;
}
}
}
</pre><pre code_snippet_id="363364" snippet_file_name="blog_20140526_22_5959525" name="code" class="java">