【发布时间】:2014-04-14 20:47:34
【问题描述】:
我是 applet/servlet 开发的新手,我遇到了一个我还没有找到解决办法的问题。
环境如下:
操作系统:Solaris 5.10
AS:iPlanet6 sp8
JRE:j2re1.4.2_04
jsse.jar 包含在 servlet 类路径中。
我的 servlet 必须通过 ldaps 连接到 ldap 服务器;我的 ldap 类如下所示
public class MyLdapClass
{
private static final String INITCTX = "com.sun.jndi.ldap.LdapCtxFactory";
public MyLdapClass(String _strHost, int _iPort, String _strLogin, String _strPassword, String _strBaseDN)
{
...
environ.put(Context.INITIAL_CONTEXT_FACTORY, INITCTX);
environ.put(Context.SECURITY_PRINCIPAL, _strLogin);
environ.put(Context.SECURITY_CREDENTIALS, _strPassword);
String strUrl = "ldap://" + _strHost + ":" + _iPort;
XTrustProvider.install();
environ.put(Context.SECURITY_PROTOCOL, "ssl");
environ.put(Context.PROVIDER_URL, strUrl);
environ.put(Context.SECURITY_AUTHENTICATION, "simple");
environ.put("com.sun.jndi.ldap.read.timeout", "5000");
}
private void connect() throws NamingException
{
try
{
this.context = new InitialLdapContext(this.environ, null);
}
catch (NamingException ne)
{
throw ne;
}
}
private void _disconnect() throws NamingException
{
try
{
this.context.close();
}
catch (NamingException ne)
{
throw ne;
}
}
}
我的 servlet(与我的问题相关的部分代码)如下所示:
public class MyServlet extends HttpServlet
{
MyLdapClass ldap;
public void init(ServletConfig paramServletConfig) throws ServletException
{
ldap = new MyLdapClass("ipaddress", port, "login", "pwd", "baseDN");
}
public void doPost(HttpServletRequest paramHttpServletRequest, HttpServletResponse paramHttpServletResponse)
throws ServletException
{
try
{
ldap.connect();
}
catch (NamingException ne)
{
throw ne;
}
...
}
}
当我从 applet 向 servlet 发布请求时,会引发如下异常:
javax.naming.CommunicationException: _ip:port_ [**Root exception is java.lang.ClassNotFoundException: javax/net/ssl/SSLSocketFactory**]
at com.sun.jndi.ldap.Connection.<init>(Unknown Source)
at com.sun.jndi.ldap.LdapClient.<init>(Unknown Source)
at com.sun.jndi.ldap.LdapClient.getInstance(Unknown Source)
at com.sun.jndi.ldap.LdapCtx.connect(Unknown Source)
at com.sun.jndi.ldap.LdapCtx.<init>(Unknown Source)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(Unknown Source)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(Unknown Source)
at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(Unknown Source)
at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(Unknown Source)
at javax.naming.spi.NamingManager.getInitialContext(Unknown Source)
at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)
at javax.naming.InitialContext.init(Unknown Source)
at javax.naming.ldap.InitialLdapContext.<init>(Unknown Source)
at MyLdapClass.connect(MyLdapClass.java:_row number_)
at MyServlet.doPost(MyServlet.java:_row number_)
at javax.servlet.http.HttpServlet.doPost(HttpServlet.java:_row number_)
at com.iplanet.server.http.servlet.NSServletRunner.invokeServletService(NSServletRunner.java:937)
at com.iplanet.server.http.servlet.NSServletRunner.Service(NSServletRunner.java:494)
Caused by: java.lang.ClassNotFoundException: javax/net/ssl/SSLSocketFactory
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at com.sun.jndi.ldap.VersionHelper12.loadClass(Unknown Source)
at com.sun.jndi.ldap.Connection.createSocket(Unknown Source)
... 20 more
Internal error: servlet service function had thrown ServletException (uri=/servlet/MyServlet): javax.servlet.ServletException: NamingException:__ip:port__, stack: javax.servlet.ServletException: NamingException:_ip:port_
如果我从 Myservlet service 方法调用 ldap.connect() 也会发生同样的情况;相反,如果我从 MyServlet 类的 init 方法调用 ldap.connect(),一切正常,但我要求连接必须按需打开,并在处理请求时关闭。
我错过了什么吗?我该如何解决?先谢谢大家了
为了完整起见,XTrustProvider 代码如下:
package jas.frontend;
import java.security.AccessController;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.PrivilegedAction;
import java.security.Provider;
import java.security.Security;
import java.security.cert.X509Certificate;
import javax.net.ssl.ManagerFactoryParameters;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactorySpi;
import javax.net.ssl.X509TrustManager;
public final class XTrustProvider extends Provider {
/**
*
*/
private static final long serialVersionUID = 1L;
private final static String NAME = "XTrustJSSE";
private final static String INFO = "XTrust JSSE Provider (implements trust factory with truststore validation disabled)";
private final static double VERSION = 1.0D;
public XTrustProvider() {
super(NAME, VERSION, INFO);
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
put("TrustManagerFactory." + TrustManagerFactoryImpl.getAlgorithm(),
TrustManagerFactoryImpl.class.getName());
return null;
}
});
}
public static void install() {
if (Security.getProvider(NAME) == null) {
Security.insertProviderAt(new XTrustProvider(), 2);
Security.setProperty("ssl.TrustManagerFactory.algorithm", TrustManagerFactoryImpl.getAlgorithm());
}
}
public final static class TrustManagerFactoryImpl extends TrustManagerFactorySpi {
public TrustManagerFactoryImpl() {}
public static String getAlgorithm() {
return "XTrust509";
}
protected void engineInit(KeyStore keystore) throws KeyStoreException {}
protected void engineInit(ManagerFactoryParameters mgrparams) throws InvalidAlgorithmParameterException {
throw new InvalidAlgorithmParameterException(XTrustProvider.NAME + " does not use ManagerFactoryParameters");
}
protected TrustManager[] engineGetTrustManagers() {
return new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {}
public void checkServerTrusted(X509Certificate[] certs, String authType) {}
} };
}
}
}
【问题讨论】:
-
奇怪 -
SSLSocketFactory应该在 JRE 1.4.2 中 - 验证它是否在rt.jar中? -
谢谢@AndersR.Bystrup... 下面一些 grep > jar tvf rt.jar | grep -i SSLSocketFactory > jar tvf jsse.jar | grep -i SSLSocketFactory 1602 Tue Jan 01 00:00:00 CET 1980 javax/net/ssl/SSLSocketFactory.class 402 Tue Jan 01 00:00:00 CET 1980 javax/net/ssl/SSLSocketFactory$1.class 1008 Tue Jan 01 00 :00:00 CET 1980 javax/net/ssl/DefaultSSLSocketFactory.class 2658 Tue Jan 01 00:00:00 CET 1980 com/sun/net/ssl/internal/ssl/SSLSocketFactoryImpl.class
-
你确定运行Applet的JRE也有SSLSocketFactory
-
@shazin 我的问题出在服务器端... servlet 应该连接,执行一些处理,然后将结果数据返回到小程序。无论如何我会检查的。谢谢
-
我将您的问题理解为从 servlet 到 LDAP 服务器的 LDAPS 调用。如果你在你的小程序中发起呼叫,我认为@shazin 有一个非常有效的观点。
标签: java servlets classnotfoundexception iplanet