NO.91 SSLPeerUnverifiedException 问题之解决(附HttpClientUtils升级版)

   最近在写一个类似抢火车票的秒杀工具,写好后,发现在某些网络(公司内某办公场地)内报SSLPeerUnverifiedException,而在其它网络却不会有任何问题(公司内另一办公场地或家里),报错主要内容:

    javax.net.ssl.SSLPeerUnverifiedException:peer not authenticated

        atcom.sun.net.ssl.internal.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:352)

 

    后查到一篇帖子提到“上面的异常信息主要意思是:证书验证不通过。就是说你所访问网站的证书不在你可以信任的证书列表中.”并且通过对比贴主和我的代码,发现了问题所在:

SSLSocketFactory ssf= new SSLSocketFactory(sslcontext);

改为

SSLSocketFactory ssf= new SSLSocketFactory(sslcontext,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

OK,经测试问题解决。

 

附完整代码:

这是HttpConnectionUtils的升级版

1. 基于Apache HttpClient4

2. 添加获取图片的方法

3. 支持https

4. 支持会话保持


上一版本原文见:

NO.19HttpConnection、HttpClient使用注意点(附http连接工具:采用HttpClient支持代理Proxy、支持用户名密码、支持域Domain模式)


【依赖包】

httpclient-4.2.2.jar

httpcore-4.2.2.jar


package amosryan.util;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.NTCredentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.auth.params.AuthPNames;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.AuthPolicy;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.auth.NTLMSchemeFactory;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class HttpClientUtils {

	private static final Logger logger = LoggerFactory
			.getLogger(HttpClientUtils.class);

	/** 连接超时时间(默认3秒 3000ms) 单位毫秒(ms) */
	private int connectionTimeout = 3000;

	/** 读取数据超时时间(默认30秒 30000ms) 单位毫秒(ms) */
	private int soTimeout = 30000;

	/** 代理主机名 */
	private String proxyHost;

	/** 代理端口 */
	private int proxyPort;

	/** 代理主机用户名 */
	private String proxyUser;

	/** 代理主机密码 */
	private String proxyPwd;

	/** 代理主机域 */
	private String proxyDomain;

	/** 字符集设置,默认UTF-8 */
	private String charset = "UTF-8";

	private Header[] httpsCookieHeaders;

	public String getProxyUser() {
		return proxyUser;
	}

	public void setProxyUser(String proxyUser) {
		this.proxyUser = proxyUser;
	}

	public String getProxyPwd() {
		return proxyPwd;
	}

	public void setProxyPwd(String proxyPwd) {
		this.proxyPwd = proxyPwd;
	}

	public String getProxyDomain() {
		return proxyDomain;
	}

	public void setProxyDomain(String proxyDomain) {
		this.proxyDomain = proxyDomain;
	}

	public int getConnectionTimeout() {
		return connectionTimeout;
	}

	public void setConnectionTimeout(int connectionTimeout) {
		this.connectionTimeout = connectionTimeout;
	}

	public String getProxyHost() {
		return proxyHost;
	}

	public void setProxyHost(String proxyHost) {
		this.proxyHost = proxyHost;
	}

	public int getProxyPort() {
		return proxyPort;
	}

	public void setProxyPort(int proxyPort) {
		this.proxyPort = proxyPort;
	}

	public int getSoTimeout() {
		return soTimeout;
	}

	public void setSoTimeout(int soTimeout) {
		this.soTimeout = soTimeout;
	}

	public String getCharset() {
		return charset;
	}

	public void setCharset(String charset) {
		this.charset = charset;
	}

	private static X509TrustManager tm = new X509TrustManager() {
		public void checkClientTrusted(X509Certificate[] xcs, String string)
				throws CertificateException {
		}

		public void checkServerTrusted(X509Certificate[] xcs, String string)
				throws CertificateException {
		}

		public X509Certificate[] getAcceptedIssuers() {
			return null;
		}
	};

	/**
	 * 获取一个针对http的HttpClient
	 */
	private HttpClient getHttpClient()// boolean useHttps
			throws KeyManagementException, NoSuchAlgorithmException {
		HttpParams httpParams = new BasicHttpParams();
		// 设置代理
		if (!StringUtils.isEmpty(proxyHost)) {
			HttpHost proxy = new HttpHost(proxyHost, proxyPort);
			httpParams.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
		}

		// 设置超时时间
		httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,
				connectionTimeout);
		httpParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, soTimeout);
		DefaultHttpClient httpclient = new DefaultHttpClient();
		httpclient.setParams(httpParams);
		// 代理需要认证
		if (proxyUser != null) {
			if (proxyDomain != null) {// NTLM认证模式
				httpclient.getAuthSchemes().register("ntlm",
						new NTLMSchemeFactory());
				httpclient.getCredentialsProvider().setCredentials(
						AuthScope.ANY,
						new NTCredentials(proxyUser, proxyPwd, proxyHost,
								proxyDomain));
				List<String> authpref = new ArrayList<String>();
				authpref.add(AuthPolicy.NTLM);
				httpclient.getParams().setParameter(
						AuthPNames.TARGET_AUTH_PREF, authpref);
			} else {// BASIC模式
				CredentialsProvider credsProvider = new BasicCredentialsProvider();
				credsProvider.setCredentials(
						new AuthScope(proxyHost, proxyPort),
						new UsernamePasswordCredentials(proxyUser, proxyPwd));
				httpclient.setCredentialsProvider(credsProvider);
			}
		}
		httpclient.addRequestInterceptor(new HttpRequestInterceptor() {
			public void process(final HttpRequest request,
					final HttpContext context) throws HttpException,
					IOException {
				if (!request.containsHeader("Accept")) {
					request.addHeader("Accept", "*/*");
				}
				if (request.containsHeader("User-Agent")) {
					request.removeHeaders("User-Agent");
				}
				if (request.containsHeader("Connection")) {
					request.removeHeaders("Connection");
				}
				request.addHeader("User-Agent",
						"Mozilla/5.0 (Windows NT 5.1; rv:8.0) Gecko/20100101 Firefox/8.0");
				request.addHeader("Connection", "keep-alive");
			}
		});
		return httpclient;
	}

	/**
	 * 获取一个针对https的HttpClient
	 */
	private HttpClient getHttpsClient() throws KeyManagementException,
			NoSuchAlgorithmException {
		HttpClient httpclient = getHttpClient();
		SSLContext sslcontext = SSLContext.getInstance("TLS");
		sslcontext.init(null, new TrustManager[] { tm }, null);
		SSLSocketFactory ssf = new SSLSocketFactory(sslcontext,
				SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
		httpclient.getConnectionManager().getSchemeRegistry()
				.register(new Scheme("https", 443, ssf));
		return httpclient;
	}

	/**
	 * 创建post请求
	 * 
	 * @param url
	 * @return HttpPost
	 */
	private HttpPost getHttpPost(String url) {
		// 创建post请求
		HttpPost post = new HttpPost(url);
		if (httpsCookieHeaders != null && httpsCookieHeaders.length > 0) {
			post.setHeaders(httpsCookieHeaders);
		}
		return post;
	}

	/**
	 * 创建get请求
	 * 
	 * @param url
	 * @return HttpGet
	 */
	private HttpGet getHttpGet(String url) {
		HttpGet get = new HttpGet(url);
		if (httpsCookieHeaders != null && httpsCookieHeaders.length > 0) {
			get.setHeaders(httpsCookieHeaders);
		}
		return get;
	}

	/**
	 * 获取response里的cookies
	 * 
	 * @param response
	 */
	private void getRequestCookieHeader(HttpResponse response) {
		Header[] responseHeaders = response.getHeaders("Set-Cookie");
		if (responseHeaders == null || responseHeaders.length <= 0) {
			return;
		}
		httpsCookieHeaders = new BasicHeader[responseHeaders.length];
		for (int i = 0; i < responseHeaders.length; i++) {
			httpsCookieHeaders[i] = new BasicHeader("Cookie",
					responseHeaders[i].getValue());
		}

	}

	/**
	 * 获取地址指向的图片并保存在指定位置
	 * @param url
	 * @param imageFilePath
	 * @return
	 * @throws KeyManagementException
	 * @throws NoSuchAlgorithmException
	 */
	public synchronized File getImage(String url, String imageFilePath)
			throws KeyManagementException, NoSuchAlgorithmException {
		File image = new File(imageFilePath);

		// 创建客户端
		HttpClient httpclient = getHttpsClient();
		HttpGet get = getHttpGet(url);
		try {
			HttpResponse response = httpclient.execute(get);
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				InputStream instream = entity.getContent();
				String fileType = FileUtils.getFileType(imageFilePath);
				ImageIO.write(ImageIO.read(instream), fileType, image);
			}
		} catch (Exception e) {
			logger.warn(e.getMessage());
			e.printStackTrace();
		} finally {
			httpclient.getConnectionManager().shutdown();
		}
		return image;
	}

	/**
	 * 以get方式请求,返回String型结果
	 * 
	 * @param url
	 * @return
	 * @throws Exception
	 */
	public String doGet(String url) throws Exception {
		HttpClient httpclient = getHttpsClient();
		HttpGet get = getHttpGet(url);
		String responseBody = null;
		try {
			HttpResponse response = httpclient.execute(get);
			getRequestCookieHeader(response);

			responseBody = IOUtils.toString(response.getEntity().getContent(),
					charset);

		} catch (java.net.SocketTimeoutException ste) {
			responseBody = ste.getMessage();
		} catch (Exception e) {
			responseBody = e.getMessage();
			logger.warn(responseBody);
			e.printStackTrace();
		} finally {
			httpclient.getConnectionManager().shutdown();
		}
		return responseBody;
	}

	/**
	 * 以post方式请求,返回String型结果
	 * 
	 * @param url
	 * @param nvps
	 * @return
	 * @throws Exception
	 */
	public String doPost(String url, List<NameValuePair> nvps) throws Exception {
		HttpClient httpclient = getHttpsClient();
		HttpPost post = getHttpPost(url);
		String responseBody = null;
		try {
			post.setEntity(new UrlEncodedFormEntity(nvps, charset));
			HttpResponse response = httpclient.execute(post);
			getRequestCookieHeader(response);

			responseBody = IOUtils.toString(response.getEntity().getContent(),
					charset);

		} catch (java.net.SocketTimeoutException ste) {
			responseBody = ste.getMessage();
		} catch (Exception e) {
			responseBody = e.getMessage();
			logger.warn(responseBody);
			e.printStackTrace();
		} finally {
			httpclient.getConnectionManager().shutdown();
		}
		return responseBody;
	}
	
	public static void main() throws Exception {
		HttpClientUtils httpClient = new HttpClientUtils();
		httpClient.setCharset("UTF-8");
		httpClient.setProxyHost(Constants.proxyHost);
		httpClient.setProxyPort(Constants.proxyPort);
		httpClient.setConnectionTimeout(3000);
		httpClient.setSoTimeout(3000);
		List<NameValuePair> parameters = new ArrayList<NameValuePair>();
		parameters.add(new BasicNameValuePair("User_Code",
				"username"));
		parameters.add(new BasicNameValuePair("Password",
				"password"));
		parameters
				.add(new BasicNameValuePair("AutoLogin", "true"));
		parameters.add(new BasicNameValuePair("VerifyCode", ""));
		String url = "******/login.do";
		String responseBody = httpClient.doPost(url, parameters);
		System.out.println(responseBody);
	}
	
}




  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值