這是本文件的舊版!
LDAP & AD
LDAP & AD都算是老東西了,會開始寫些教學是因為遇到與它的整合。內容隨著我的學習會慢慢增加,如果我有空寫的話~XD。
LDAP + RestAPI + Digest Auth?
目前遇到的問題是: LDAP使用者是否可以透過RestAPI進行Digest Auth?
我認為有困難。
由於認證行為是交給LDAP Server,RestAPI Web層只負責forwarding;而Digest Auth中的密碼會被根據Http Request種類、密碼等等內容一起MD5 encoding過。如果無法取得明文,除非LDAP Server允許接受一樣的方式。
SunCertPathBuilderException
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
參考此篇教學,執行以下command將root ca給匯入到Java keystore中,changeit是預設密碼,如果要用記得要改:
keytool -importcert -trustcacerts -keystore /opt/jdk1.8.0_60/jre/lib/security/cacerts -storepass changeit -noprompt -alias tonytest -file /etc/ldap/ssl/rootca.crt Certificate was added to keystore列出現有的ca:
keytool -list -keystore /opt/jdk1.8.0_60/jre/lib/security/cacerts -storepass changeit查看看測試的ca:
./keytool -list -keystore /opt/jdk1.8.0_60/jre/lib/security/cacerts -storepass changeit | grep tony tonytest, Mar 23, 2016, trustedCertEntry,刪除測試的ca:
./keytool -delete -keystore /opt/jdk1.8.0_60/jre/lib/security/cacerts -storepass changeit -alias tonytest
TLS already started
在透過Spring Security使用TLS後,會發生TLS already started的例外。經過trace並從網路上文章中發現,這是由於connection pool造成的。目前只要設定LdapContextSource以下內容,即可取消connection pool暫時解決:
ldapContextSource.setCacheEnvironmentProperties(false); ldapContextSource.setPooled(false);會出現這問題,也有可能你是使用ldaps+636 port去做存取而產生的。(reference link)
Test Spring API
public class Tester { public static void main(String[] args) { try { LdapContextSource contextSource = new LdapContextSource(); //contextSource.setUrl("ldap://superserver.tony.org:389"); //contextSource.setUrl("ldap://superserver.tony.org:389"); contextSource.setUrl("ldap://10.134.15.131:389"); contextSource.setBase("DC=tony,DC=org"); contextSource.setUserDn("CN=admin,DC=tony,DC=org"); contextSource.setPassword("123456"); contextSource.afterPropertiesSet(); DefaultTlsDirContextAuthenticationStrategy strategy = new DefaultTlsDirContextAuthenticationStrategy(){ @Override protected void applyAuthentication(LdapContext ctx, String userDn, String password) throws NamingException { super.applyAuthentication(ctx, userDn, password); ctx.addToEnvironment("com.sun.jndi.ldap.read.timeout", "20000"); } }; strategy.setHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String paramString, SSLSession paramSSLSession) { System.out.println("ignore verify"); return true; } }); contextSource.setAuthenticationStrategy(strategy); LdapTemplate ldapTemplate = new LdapTemplate(contextSource); ldapTemplate.afterPropertiesSet(); Filter filter = new EqualsFilter("uid", "tonylin"); boolean authed = ldapTemplate.authenticate("ou=supermicro", filter.encode(), "123456"); System.out.println("Authenticated: " + authed); } catch (Exception e) { e.printStackTrace(); } finally { ThreadUtil.sleep(15000); } } }
Hashtable<String, Object> env = new Hashtable<String, Object>(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://10.134.15.131:389/dc=tony,dc=org"); // Authenticate as C. User and password "mysecret" //env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5"); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=tony,dc=org"); env.put(Context.SECURITY_CREDENTIALS, "123456"); // Create the initial context DirContext ctx = new InitialDirContext(env); NamingEnumeration<SearchResult> srs = ctx.search("", null); while( srs.hasMore() ){ SearchResult sr = srs.next(); System.out.println(sr); } ctx.close();