需求:員工在線更改域賬號密碼;解鎖域賬號整胃;
環(huán)境:SpringBoot+Java8+Ldap杠愧。
必要條件:一個能改密碼和解鎖賬號的超級管理員賬號;
認證LDAP服務律想,跳過證書
連接LDAP猎莲,代碼如下
private static DirContext ctx = null;
private static final String adminName = "cn=aaa,ou=AAAA,DC=cccc,DC=dddd,DC=com";
private static final String adminPassword = "43sdrs";
private static final String ldapUrl = "ldaps://aaa.ddddd.com:636";
public static void ldapConnect() throws NamingException {
Hashtable<Object, Object> env = new Hashtable<Object, Object>();
//解決No subject alternative DNS name xxxxx的錯誤
Security.setProperty("jdk.tls.disabledAlgorithms", "");
System.setProperty("com.sun.jndi.ldap.object.disableEndpointIdentification", "true");
env.put(Context.SECURITY_PROTOCOL, "ssl");
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, adminName);
env.put(Context.SECURITY_CREDENTIALS, adminPassword);
env.put(Context.PROVIDER_URL, ldapUrl);
//繞過證書認證,別忘記輸入正確的類路徑
env.put("java.naming.ldap.factory.socket", "com.xxx.bbb.DummySSLSocketFactory");
ctx = new InitialDirContext(env);
}
跳過證書
需要用到三個類DummySSLSocketFactory技即,DummyTrustManager和TrustAllTrustManager
- DummySSLSocketFactory
public class DummySSLSocketFactory extends SSLSocketFactory {
private SSLSocketFactory factory;
public DummySSLSocketFactory() {
try {
SSLContext sslcontext = SSLContext.getInstance("TLS");
sslcontext.init(null, new TrustManager[]{new DummyTrustManager()}, new java.security.SecureRandom());
factory = (SSLSocketFactory) sslcontext.getSocketFactory();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static SocketFactory getDefault() {
return new DummySSLSocketFactory();
}
public Socket createSocket(Socket socket, String s, int i, boolean flag) throws IOException {
return factory.createSocket(socket, s, i, flag);
}
public Socket createSocket(InetAddress inaddr, int i, InetAddress inaddr1, int j) throws IOException {
return factory.createSocket(inaddr, i, inaddr1, j);
}
public Socket createSocket(InetAddress inaddr, int i) throws IOException {
return factory.createSocket(inaddr, i);
}
public Socket createSocket(String s, int i, InetAddress inaddr, int j) throws IOException {
return factory.createSocket(s, i, inaddr, j);
}
public Socket createSocket(String s, int i) throws IOException {
return factory.createSocket(s, i);
}
public String[] getDefaultCipherSuites() {
return factory.getSupportedCipherSuites();
}
public String[] getSupportedCipherSuites() {
return factory.getSupportedCipherSuites();
}
}
- DummyTrustManager
public class DummyTrustManager implements X509TrustManager {
public void checkClientTrusted( X509Certificate[] cert, String authType) {
return;
}
public void checkServerTrusted( X509Certificate[] cert, String authType) {
return;
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
- TrustAllTrustManager
public class TrustAllTrustManager implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager {
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
return;
}
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
return;
}
}
修改域賬號密碼
public static void updatePwd(String account, String newPwd) throws Exception {
String userDN = getUserDomain(account);
if (StringUtils.isBlank(userDN)) {
return;
}
String newQuotedPassword = String.format("\"%s\"", newPwd);
byte[] newUnicodePassword;
newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");
ModificationItem[] mods = new ModificationItem[1];
mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("unicodePwd", newUnicodePassword));
ctx.modifyAttributes(userDN, mods);
}
解鎖域賬號
public static void unlock(String account) throws NamingException {
String userDN = getUserDomain(account);
log.info("userDN:{}", userDN);
BasicAttributes basicAttributes = new BasicAttributes();
//512,表示Normal即正常賬號
basicAttributes.put("userAccountControl", "512");
//lockOutTime表示已經(jīng)鎖住的事件著洼,需要置為0可以立即解鎖
basicAttributes.put("lockOutTime", "0");
ctx.modifyAttributes(userDN, DirContext.REPLACE_ATTRIBUTE, basicAttributes);
}
獲取用戶的域賬號信息
private static String getUserDomain(String account) throws NamingException {
String userDN = null;
SearchControls contro = new SearchControls();
contro.setSearchScope(2);
NamingEnumeration<SearchResult> en = ctx.search("DC=aaa,DC=bbbbb,DC=com", "cn=" + account, contro);
if (en == null || !en.hasMoreElements()) {
return null;
}
while (en.hasMoreElements()) {
Object obj = en.nextElement();
if (obj instanceof SearchResult) {
SearchResult si = (SearchResult) obj;
Attributes attrs = si.getAttributes();
userDN = (String) attrs.get("distinguishedName").get();
break;
}
}
return userDN;
}
關(guān)閉LDAP連接
public static void closeConnect() {
try {
if (ctx != null) {
ctx.close();
}
} catch (NamingException e) {
e.printStackTrace();
}
}
示例
/**
解鎖域賬號
**/
public static void main(String[] args) {
try {
LdapSSLUtil.ldapConnect();
LdapSSLUtil.enableUser(adName);
} catch (Exception e) {
log.error("發(fā)送錯誤:{}", e.getMessage(), e);
} finally {
LdapSSLUtil.closeConnect();
}
}