springboot配置ldaps連接方式
springboot配置ldaps連接
spring boot配置ldap 連接時,通過ldap://xxxxx:389 連接,一般來說都能成功,但是如果配置ldap ssl 連接,ldaps://xxxx:636 那么很大概率會出現(xiàn)
javax.naming.CommunicationException: simple bind failed: xxxxxtest.com.local:636
這種異常 。
百度,谷歌搜索 大部分解決方案是需要從ldap 服務(wù)器上導(dǎo)出證書,然后再通過Java的keytool 工具導(dǎo)入證書,比較繁瑣,我也沒試過好不好使,反正從服務(wù)器上導(dǎo)出證書那一步就很煩了。
說一下如何代碼配置ldap跳過ssl
直接上代碼。
package com.github.wxiaoqi.security.common.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.LdapContextSource;
import java.util.Hashtable;
import java.util.Objects;
/**
* @author margo
* @date 2021/11/4
*/
@Slf4j
// @ConditionalOnExpression("${ldap.enabled:false}")
public class LdapConfiguration {
private LdapTemplate ldapTemplate;
@Value("${ldap.url}")
private String ldapUrl;
@Value("${ldap.basedc}")
private String ldapBaseDc;
@Value("${ldap.username}")
private String ldapUsername;
@Value("${ldap.passwd}")
private String ldapPasswd;
/**
* 繼承LdapContextSource重寫getAnonymousEnv方法來加載,
* 使連接ldap時用SSL連接(由于修改AD密碼時必須使用SSL連接)
*/
public class SsldapContextSource extends LdapContextSource {
@Override
public Hashtable<String, Object> getAnonymousEnv(){
Hashtable<String, Object> anonymousEnv = super.getAnonymousEnv();
anonymousEnv.put("java.naming.security.protocol", "ssl");
anonymousEnv.put("java.naming.ldap.factory.socket", CustomSslSocketFactory.class.getName());
return anonymousEnv;
}
}
@Bean
public LdapContextSource contextSource() {
SsldapContextSource ldapContextSource = new SsldapContextSource();
ldapContextSource.setBase(ldapBaseDc);
ldapContextSource.setUrl(ldapUrl);
ldapContextSource.setUserDn(ldapUsername);
ldapContextSource.setPassword(ldapPasswd);
ldapContextSource.setPooled(false);
ldapContextSource.setReferral("follow");
ldapContextSource.afterPropertiesSet();
return ldapContextSource;
}
@Bean
public LdapTemplate ldapTemplate(LdapContextSource contextSource) {
if (Objects.isNull(contextSource)) {
throw new RuntimeException("ldap contextSource error");
}
if (null == ldapTemplate) {
ldapTemplate = new LdapTemplate(contextSource);
}
return ldapTemplate;
}
}package com.github.wxiaoqi.security.common.config;
import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
/**
* 自定義的SSL工廠里面加載自己實(shí)現(xiàn)X509TrustManager,信任自簽證書
* @author cb
*/
public class CustomSslSocketFactory extends SSLSocketFactory {
private SSLSocketFactory socketFactory;
public CustomSslSocketFactory() {
try {
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, new TrustManager[]{new DummyTrustmanager()}, new SecureRandom());
socketFactory = ctx.getSocketFactory();
} catch (Exception ex) {
ex.printStackTrace(System.err);
}
}
public static SocketFactory getDefault() {
return new CustomSslSocketFactory();
}
@Override
public String[] getDefaultCipherSuites() {
return socketFactory.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return socketFactory.getSupportedCipherSuites();
}
@Override
public Socket createSocket(Socket socket, String string, int num, boolean bool) throws IOException {
return socketFactory.createSocket(socket, string, num, bool);
}
@Override
public Socket createSocket(String string, int num) throws IOException, UnknownHostException {
return socketFactory.createSocket(string, num);
}
@Override
public Socket createSocket(String string, int num, InetAddress netAdd, int i) throws IOException, UnknownHostException {
return socketFactory.createSocket(string, num, netAdd, i);
}
@Override
public Socket createSocket(InetAddress netAdd, int num) throws IOException {
return socketFactory.createSocket(netAdd, num);
}
@Override
public Socket createSocket(InetAddress netAdd1, int num, InetAddress netAdd2, int i) throws IOException {
return socketFactory.createSocket(netAdd1, num, netAdd2, i);
}
/**
* 證書
*/
public static class DummyTrustmanager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] cert, String string) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] cert, String string) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[0];
}
}
}主要的配置是 CustomSslSocketFactory 這個類,其他的正常配置。
配置好后啟動應(yīng)用,又出現(xiàn)了另外一個錯誤,
javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException
在啟動main方法中加上一行環(huán)境變量配置即可
@EnableEurekaClient
@SpringBootApplication
@EnableConfigurationProperties
@EnableTransactionManagement
@Import(value = {RedissonConfig.class, GatewayReqInterceptor.class, UserInfoInterceptor.class, InterceptorConfig.class, CoreConfig.class, AuthConfig.class, AuthServerRunner.class, LdapConfiguration.class})
@EnableScheduling
public class WxCpApplication {
public static void main(String[] args) {
System.setProperty("com.sun.jndi.ldap.object.disableEndpointIdentification", "true"); // important resolve javax.net.ssl.SSLHandshakeException
SpringApplication.run(WxCpApplication.class, args);
}
}
System.setProperty("com.sun.jndi.ldap.object.disableEndpointIdentification", "true"); 這行總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
- SpringLDAP連接LDAPS證書報(bào)錯問題及解決
- springboot操作ldap全過程
- SpringBoot整合Ldap的實(shí)現(xiàn)示例
- Spring Security LDAP實(shí)現(xiàn)身份驗(yàn)證的項(xiàng)目實(shí)踐
- SpringBoot整合LDAP的流程分析
- 淺談Spring Security LDAP簡介
- Vue+Jwt+SpringBoot+Ldap完成登錄認(rèn)證的示例代碼
- Spring Boot中使用LDAP來統(tǒng)一管理用戶信息的示例
- Spring Boot 連接LDAP的方法
- Spring LDAP目錄服務(wù)的使用示例
相關(guān)文章
解析Java的Spring框架的基本結(jié)構(gòu)
這篇文章主要介紹了Java的Spring框架的基本結(jié)構(gòu),作者從Spring的設(shè)計(jì)角度觸發(fā)解析其基礎(chǔ)的架構(gòu)內(nèi)容,需要的朋友可以參考下2016-03-03
使用Spring的ApplicationEvent實(shí)現(xiàn)本地事件驅(qū)動的實(shí)現(xiàn)方法
本文介紹了如何使用Spring的ApplicationEvent實(shí)現(xiàn)本地事件驅(qū)動,通過自定義事件和監(jiān)聽器,實(shí)現(xiàn)模塊之間的松耦合,提升代碼的可維護(hù)性和擴(kuò)展性。同時還介紹了異步事件和事件傳遞的相關(guān)知識2023-04-04
java實(shí)現(xiàn)新浪微博Oauth接口發(fā)送圖片和文字的方法
這篇文章主要介紹了java實(shí)現(xiàn)新浪微博Oauth接口發(fā)送圖片和文字的方法,涉及java調(diào)用新浪微博Oauth接口的使用技巧,具有一定參考接借鑒價值,需要的朋友可以參考下2015-07-07
SpringBoot整合Mybatis,解決TypeAliases配置失敗的問題
這篇文章主要介紹了SpringBoot整合Mybatis,解決TypeAliases配置失敗的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07
介紹Java的大數(shù)類(BigDecimal)和八種舍入模式
在實(shí)際應(yīng)用中,需要對更大或者更小的數(shù)進(jìn)行運(yùn)算和處理。Java在java.math包中提供的API類BigDecimal,用來對超過16位有效位的數(shù)進(jìn)行精確的運(yùn)算。本文將介紹Java中的大數(shù)類BigDecimal及其八種舍入模式,有需要的可以參考借鑒。2016-08-08

