Java 使用httpclient 4.1.2连接到https会导致org.apache.http.client.ClientProtocolException
我已成功地在android中使用发布到https服务器,接受所有证书 现在,我正在用JAVA尝试同样的方法向https服务器发送接受所有证书的邮件 我从上面的url修改了Java 使用httpclient 4.1.2连接到https会导致org.apache.http.client.ClientProtocolException,java,ssl,httpclient,Java,Ssl,Httpclient,我已成功地在android中使用发布到https服务器,接受所有证书 现在,我正在用JAVA尝试同样的方法向https服务器发送接受所有证书的邮件 我从上面的url修改了EasySSLSocketFactory类,因为SocketFactory、LayeredSocketFactory类在httpclient 4.1.2版本中不推荐使用EasyX509TrustManager以上url中的类保持不变。这是我修改过的EasySSLSocketFactory。我已经标记了我修改过的类 /* * L
EasySSLSocketFactory
类,因为SocketFactory、LayeredSocketFactory
类在httpclient 4.1.2版本中不推荐使用<代码>EasyX509TrustManager以上url中的类保持不变。这是我修改过的EasySSLSocketFactory
。我已经标记了我修改过的类
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.scheme.SchemeSocketFactory;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
public class EasySSLSocketFactory implements SchemeSocketFactory
{
private SSLContext sslcontext = null;
private static SSLContext createEasySSLContext() throws IOException {
try {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new TrustManager[] { new EasyX509TrustManager(null) }, null);
return context;
} catch (Exception e) {
throw new IOException(e.getMessage());
}
}
private SSLContext getSSLContext() throws IOException {
if (this.sslcontext == null) {
this.sslcontext = createEasySSLContext();
}
return this.sslcontext;
}
/**
* @see org.apache.http.conn.scheme.SchemeSocketFactory#isSecure(java.net.Socket)
*/
public boolean isSecure(Socket socket) throws IllegalArgumentException {
return true;
}
// -------------------------------------------------------------------
// javadoc in org.apache.http.conn.scheme.SocketFactory says :
// Both Object.equals() and Object.hashCode() must be overridden
// for the correct operation of some connection managers
// -------------------------------------------------------------------
public boolean equals(Object obj) {
return ((obj != null) && obj.getClass().equals(
EasySSLSocketFactory.class));
}
public int hashCode() {
return EasySSLSocketFactory.class.hashCode();
}
//this method is modified
@Override
public Socket connectSocket(Socket sock, InetSocketAddress remoteAddress,
InetSocketAddress localAddress, HttpParams params) throws IOException,
UnknownHostException, ConnectTimeoutException {
int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
int soTimeout = HttpConnectionParams.getSoTimeout(params);
SSLSocket sslsock = (SSLSocket) ((sock != null) ? sock : createSocket(params));
if (localAddress != null) {
// we need to bind explicitly
sslsock.bind(localAddress);
}
sslsock.connect(remoteAddress, connTimeout);
sslsock.setSoTimeout(soTimeout);
return sslsock;
}
//this method is modified
@Override
public Socket createSocket(HttpParams arg0) throws IOException {
return getSSLContext().getSocketFactory().createSocket();
}
}
这是我的httpclient。由于使用了httpclient 4.1.2,这个类也被修改了
public class MyHttpClient extends DefaultHttpClient {
/** The time it takes for our client to timeout */
public static final int HTTP_TIMEOUT = 30 * 1000; // milliseconds
public static final int SOCKET_TIMEOUT = 50 * 1000; // milliseconds
public MyHttpClient() {
}
@Override
protected ClientConnectionManager createClientConnectionManager() {
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
// Register for port 443 our SSLSocketFactory to the ConnectionManager
registry.register(new Scheme("https", 443, new EasySSLSocketFactory()));
//setting the httpparams
HttpParams params = new BasicHttpParams();
//params.setParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 1);
//params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean(1));
params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, false);
//HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, "utf8");
return new SingleClientConnManager(registry);
}
}
我正试图以以下方式连接
ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
postParameters.add(new BasicNameValuePair("userid", userid));
postParameters.add(new BasicNameValuePair("password", password));
String newresponse = null;
BufferedReader in = null;
try{
DefaultHttpClient client = new MyHttpClient();
try {
HttpPost req = new HttpPost(my https url);
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(postParameters);
req.setEntity(formEntity);
HttpResponse resp = client.execute(req);
in = new BufferedReader(new InputStreamReader(resp.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line + NL);
}
in.close();
newresponse = sb.toString();
}catch(Exception e){
LOGGER.error("Exception", e);
}finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
LOGGER.error("IOException: ",e);
}
}
}
} catch(Exception e){
LOGGER.debug("Connection Exception: ",e);
}
我尝试访问的服务器正在使用我没有的来自verisign的证书。因此我尝试接受所有证书。将来我将更改此设置
有人能让它工作吗?
提前感谢。您的
EasySslocketFactory
还必须实现LayeredSchemeSocketFactory
接口,如果您希望它支持SSL隧道功能。您还需要注册SSLSocketFactory的方案:
httpClient.getConnectionManager().getSchemeRegistry().register(
new Scheme("https", 443, SSLSocketFactory.getSystemSocketFactory())
);
@oleg-谢谢你的回复。我会尝试一下,并让你保持联系。@oleg-我尝试过实现它,效果非常好。非常感谢
httpClient.getConnectionManager().getSchemeRegistry().register(
new Scheme("https", 443, SSLSocketFactory.getSystemSocketFactory())
);