差異處

這裏顯示兩個版本的差異處。

連向這個比對檢視

Both sides previous revision 前次修改
下次修改
前次修改
java:ldap:spring:ldapauthenticationprovider:secureconnection [2016/05/10 00:18]
tony
java:ldap:spring:ldapauthenticationprovider:secureconnection [2023/06/25 09:48] (目前版本)
行 7: 行 7:
   * SSL與TLS: 使用ldaps,通常port為636,為加密連線。TLS是用來取代SSL的;一般用於client-server溝通,如https。   * SSL與TLS: 使用ldaps,通常port為636,為加密連線。TLS是用來取代SSL的;一般用於client-server溝通,如https。
   * StartTLS: 使用ldap,通常port為389,是非加密連線的擴充。連線時會透過定義好的溝通方式,將連線升級為加密連線,可以是SSL也可以是TLS;一般用於server內部溝通。   * StartTLS: 使用ldap,通常port為389,是非加密連線的擴充。連線時會透過定義好的溝通方式,將連線升級為加密連線,可以是SSL也可以是TLS;一般用於server內部溝通。
-TLS和StartTLS非常容易混淆,甚至認為它是同種東西。像LdapAdmin、YAST2就是把StartTLS當TLS,而Apache Studio是稱為StartTLS extension。+TLS和StartTLS非常容易混淆,甚至認為它是同種東西。像LdapAdmin、Linux、Cisco Firesight等就是把StartTLS當TLS,而Apache Studio、SonicWall是稱為StartTLS或StartTLS extension。 
 +==== SSL ==== 
 +要使用SSL只要將protocol改為ldaps並注意使用的port即可,我分別以驗證成功與失敗做例子:​ 
 +<code java> 
 +@Test 
 +public void testSSL(){ 
 + LdapContextSource contextSource = new LdapContextSource();​ 
 + contextSource.setUrl("​ldaps://​192.168.1.13:​636"​);​ 
 + contextSource.setBase("​dc=testldap,​dc=org"​);​ 
 + contextSource.setUserDn("​cn=admin,​dc=testldap,​dc=org"​);​ 
 + contextSource.setPassword("​123456"​);​ 
 + contextSource.afterPropertiesSet();​ 
 + 
 + LdapAuthenticationProvider provider = createProvider(contextSource);​ 
 +  
 + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("​tonylin",​ "​123456"​);​ 
 + try { 
 + Authentication ret = provider.authenticate(token);​ 
 + Collection<?​ extends GrantedAuthority>​ authorities = ret.getAuthorities();​ 
 + assertEquals(1,​ authorities.size());​ 
 + assertEquals("​mis",​ authorities.toArray(new GrantedAuthority[0])[0].getAuthority());​ 
 + } catch( Exception e ){ 
 + fail(); 
 +
 +  
 + token = new UsernamePasswordAuthenticationToken("​tonylin",​ "​12345678"​);​ 
 + try { 
 + provider.authenticate(token);​ 
 + fail(); 
 + } catch( BadCredentialsException e ){ 
 + assertEquals("​Bad credentials",​ e.getMessage());​ 
 +
 +
 + 
 +private LdapAuthenticationProvider createProvider(LdapContextSource contextSource){ 
 + FilterBasedLdapUserSearch userSearch = new FilterBasedLdapUserSearch("​ou=sw",​ "​uid={0}",​ contextSource);​ 
 + BindAuthenticator authenticator = new BindAuthenticator(contextSource);​ 
 + authenticator.setUserSearch(userSearch);​ 
 +  
 + DefaultLdapAuthoritiesPopulator authoritiesPopulator = new DefaultLdapAuthoritiesPopulator(contextSource,​ "​ou=sw"​);​ 
 +  
 + authoritiesPopulator.setGroupSearchFilter("​uniqueMember={0}"​);​ 
 + authoritiesPopulator.setConvertToUpperCase(false);​ 
 + authoritiesPopulator.setRolePrefix(""​);​ 
 + authoritiesPopulator.setSearchSubtree(true);​ 
 +  
 + return new LdapAuthenticationProvider(authenticator,​ authoritiesPopulator);​  
 +
 +</​code>​ 
 +==== StartTLS ==== 
 +Spring提供了DefaultTlsDirContextAuthenticationStrategy讓你可以輕鬆使用TLS,當然也可以不透過它自己使用JNDI達到目的。與SSL的不同在於,DefaultTlsDirContextAuthenticationStrategy在做handshake後,會做hostname的verify,為了測試我們透過override setHostnameVerifier去跳過;而在驗證錯誤時,會是接到AuthenticationException的例外:​ 
 +<code java> 
 +@Test 
 +public void testTLS(){ 
 + LdapContextSource contextSource = new LdapContextSource();​ 
 + contextSource.setUrl("​ldap://​192.168.1.13:​389"​);​ 
 + contextSource.setBase("​dc=testldap,​dc=org"​);​ 
 + contextSource.setUserDn("​cn=admin,​dc=testldap,​dc=org"​);​ 
 + contextSource.setPassword("​123456"​);​ 
 +  
 + DefaultTlsDirContextAuthenticationStrategy strategy = new DefaultTlsDirContextAuthenticationStrategy();​ 
 + strategy.setHostnameVerifier((hostname,​ sslsession) -> { 
 + return true; 
 + }); 
 + contextSource.setAuthenticationStrategy(strategy);​ 
 + contextSource.afterPropertiesSet();​ 
 +  
 + LdapAuthenticationProvider provider = createProvider(contextSource);​ 
 +  
 + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("​tonylin",​ "​123456"​);​ 
 + try { 
 + Authentication ret = provider.authenticate(token);​ 
 + Collection<?​ extends GrantedAuthority>​ authorities = ret.getAuthorities();​ 
 + assertEquals(1,​ authorities.size());​ 
 + assertEquals("​mis",​ authorities.toArray(new GrantedAuthority[0])[0].getAuthority());​ 
 + } catch( Exception e ){ 
 + fail(e.getMessage());​ 
 +
 +  
 + token = new UsernamePasswordAuthenticationToken("​tonylin",​ "​12345678"​);​ 
 + try { 
 + provider.authenticate(token);​ 
 + fail(); 
 + } catch( AuthenticationException e ){ 
 + assertTrue(e.getMessage().contains("​Invalid Credentials"​));​ 
 +
 +
 +</​code>​ 
 +如果在連不到LDAP server的情況下,通常都要等待20秒。我們可以透過以下方式去調整連線與從Server讀取資料的timeout:​ 
 +<code java> 
 +Map<​String,​Object>​ baseEnv = new HashMap<>​();​ 
 +baseEnv.put("​com.sun.jndi.ldap.read.timeout",​ "​1000"​);​ 
 +baseEnv.put("​com.sun.jndi.ldap.connect.timeout",​ "​1000"​);​ 
 +  
 +contextSource.setBaseEnvironmentProperties(baseEnv);​ 
 +</​code>​ 
 +如果出現TLS already started的錯誤,這可能是spring connection pool造成的,可以透過設定以下flag取消pool暫時解決;使用ldaps+StartTLS也會有一樣問題。 
 +<code java> 
 +ldapContextSource.setCacheEnvironmentProperties(false);​ 
 +ldapContextSource.setPooled(false);​ 
 +</​code>​ 
 +===== 最後 ===== 
 +除了以上內容外,還有些議題沒特別說明:​ 
 +  * **SSL + VerifyHostname**:​ Hostname驗證是為了抵禦中間人攻擊,因此SSL應也需要Hostname驗證。目前我已經有做法可以解決。 
 +  * **Disable Connection Pool**: Connection Pool是為了減少重建連線的Effort,但目前Spring的StartTLS並無法正常使用。 
 +這些議題有機會再研究與分享
 ===== Reference ===== ===== Reference =====
   * [[https://​www.fastmail.com/​help/​technical/​ssltlsstarttls.html|SSL VS. TLS VS. STARTTLS]]   * [[https://​www.fastmail.com/​help/​technical/​ssltlsstarttls.html|SSL VS. TLS VS. STARTTLS]]
行 15: 行 120:
   * [[http://​www.informationsecurity.com.tw/​article/​article_detail.aspx?​aid=5734|SSL與TLS差異]]   * [[http://​www.informationsecurity.com.tw/​article/​article_detail.aspx?​aid=5734|SSL與TLS差異]]
   * [[http://​www.chicagotech.net/​Routers/​sonicwallissue3.htm|UI Design of SonicWall]]   * [[http://​www.chicagotech.net/​Routers/​sonicwallissue3.htm|UI Design of SonicWall]]
 +  * [[http://​www.cisco.com/​c/​en/​us/​support/​docs/​security/​firesight-management-center/​118738-configure-firesight-00.html|UI Design of Firesight system]] 
 +  * [[http://​www.derekseaman.com/​2011/​06/​citrix-netscaler-active-directory.html|UI Design of Citrix-Netscaler]] 
 +  * [[http://​www.openldap.org/​faq/​data/​cache/​1063.html|TLS already started - Connection Pool]] 
 +  * [[http://​forum.spring.io/​forum/​spring-projects/​data/​ldap/​19764-tls-and-setupauthenticatedenvironment|TLS already started - don't use ldaps]]
 =====  ===== =====  =====
 ---- ----
 \\ \\
 ~~DISQUS~~ ~~DISQUS~~