首页

通过TLSv1.2定义SSLContext解决"javax.net.ssl.SSLException: Received fatal alert: protocol_version"示例代码

标签:SSLContext,SSLException,protocol_version,CloseableHttpClient,HttpClients,SSLConnectionSocketFactory     发布时间:2020-02-19   

一、问题描述

通过java.net.URLConnection下载https请求链接,报“javax.net.ssl.SSLException: Received fatal alert: protocol_version”异常,详情错误日志>>

javax.net.ssl.SSLException: Received fatal alert: protocol_version@b@	at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)@b@	at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)@b@	at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1979)@b@	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1086)@b@	at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1332)@b@	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1359)@b@	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1343)@b@	at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)@b@	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)@b@	at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153)@b@	at com.xwood.craw.crawler.spider.core.DownLoadHandler.httpsExecute(DownLoadHandler.java:167)@b@	at com.xwood.craw.crawler.spider.core.DownLoadHandler.main(DownLoadHandler.java:243)

二、代码示例

1、上面报错代码示例(对于http链接资源可以正常获取数据,对于https资源就报SSLException异常错误)

package com.xwood.craw.crawler.spider.core;@b@@b@import java.io.BufferedInputStream;@b@import java.io.BufferedOutputStream;@b@import java.io.File;@b@import java.io.FileOutputStream;@b@import java.net.SocketTimeoutException;@b@import java.net.URL;@b@import java.net.URLConnection;@b@import java.util.HashMap;@b@import java.util.Map;@b@@b@public class DownLoadHandler  extends  DefaultHttp{@b@	@b@	@b@	public  void  httpsExecute(String eurl,String eoutpath){@b@		try {@b@			File f = new File(eoutpath);@b@			if (f.exists()){@b@				f.delete();@b@			}@b@			@b@			URL _url = new URL(eurl); @b@			try {@b@				URLConnection urlconn = _url.openConnection();@b@				urlconn.setConnectTimeout(30000);@b@				urlconn.connect();@b@			} catch (SocketTimeoutException ee) {@b@				return ;@b@			}@b@			@b@	        BufferedInputStream bis = new BufferedInputStream(_url.openStream());@b@	        if(eoutpath.lastIndexOf("/")!=-1){@b@		        File _exists_file=new File(eoutpath.substring(0, eoutpath.lastIndexOf("/")));@b@		        if(!_exists_file.exists())@b@		        	_exists_file.mkdirs();@b@	        }@b@	        @b@	        FileOutputStream out=new FileOutputStream(eoutpath);@b@	        BufferedOutputStream bos = new BufferedOutputStream(out);  @b@	        @b@	        byte buf[] = new byte[10000];  @b@	        int len;  @b@	        @b@	        int isRefered=bis.read();@b@	        if(isRefered==-1){@b@	        	Map<String,String>  tmpHeaders=new HashMap<String,String>();@b@	        	tmpHeaders.put("Referer", eurl);@b@	        	this.setHeaders(tmpHeaders);@b@	        	try {@b@					bis = new BufferedInputStream(this.doGetStream(eurl,@b@							30000));@b@				} catch (Exception e) {@b@					return;@b@				}@b@	        } @b@	        @b@	        while((len=bis.read(buf)) != -1){  @b@	 	        bos.write(buf, 0, len);  @b@	 	    }  @b@	       @b@	        bos.close();  @b@	        out.close();  @b@	        bis.close(); @b@		} catch (Exception e) {@b@			e.printStackTrace();@b@		}@b@	}@b@ @b@	public static void main(String[] args){@b@		new DownLoadHandler().httpsExecute("https://repo.maven.apache.org/maven2/abbot/abbot/0.12.3/abbot-0.12.3.pom","C:/temp/apache-maven2/abbot-0.12.3.pom");@b@	}@b@@b@}
package com.xwood.craw.crawler.spider.core;@b@@b@import java.io.File;@b@import java.io.InputStream;@b@import java.util.ArrayList;@b@import java.util.List;@b@import java.util.Map;@b@import java.util.Set;@b@@b@import org.apache.commons.io.FileUtils;@b@import org.apache.http.HttpEntity;@b@import org.apache.http.HttpResponse;@b@import org.apache.http.NameValuePair;@b@import org.apache.http.client.HttpClient;@b@import org.apache.http.client.entity.UrlEncodedFormEntity;@b@import org.apache.http.client.methods.HttpGet;@b@import org.apache.http.client.methods.HttpPost;@b@import org.apache.http.cookie.Cookie;@b@import org.apache.http.entity.StringEntity;@b@import org.apache.http.impl.client.AbstractHttpClient;@b@import org.apache.http.impl.client.DefaultHttpClient;@b@import org.apache.http.message.BasicNameValuePair;@b@import org.apache.http.params.CoreConnectionPNames;@b@import org.apache.http.util.EntityUtils;@b@@b@@b@/**@b@ * 对HttpClient进行封装,默认的HTTP请求工具@b@ */@b@@SuppressWarnings("deprecation")@b@public class DefaultHttp {@b@	@b@	private static final String DEFAULT_CHARSET = "utf-8";@b@	//http字符集@b@	private String charset = DEFAULT_CHARSET;@b@	//请求参数@b@	private Map<String, String> params;@b@	//http包头@b@	private Map<String,String> headers;@b@	@b@	private HttpClient httpClient;@b@	@b@	private HttpResponse httpResponse;@b@	@b@	private InputStream httpStream;@b@	@b@	public DefaultHttp(){@b@		httpClient = new DefaultHttpClient(); @b@	}@b@	@b@	/**@b@	 * 设置字符编码@b@	 * @param charset@b@	 * @return@b@	 */@b@	public DefaultHttp setCharset(String charset){@b@		this.charset = (charset!=null && !"".equals(charset.trim()))?charset:DEFAULT_CHARSET;@b@		return this;@b@	}@b@	/**@b@	 * 设置From Data参数@b@	 * @param params@b@	 * @return@b@	 */@b@	public DefaultHttp setParams(Map<String, String> params){@b@		this.params = params;@b@		return this;@b@	}@b@	@b@	public DefaultHttp setHeaders(Map<String,String> headers){@b@		this.headers = headers;@b@		return this;@b@	}@b@	@b@	/**@b@	 * 发送一个Post请求@b@	 * @param reqUrl@b@	 * @return@b@	 * @throws Exception@b@	 */@b@	public DefaultHttp doPost(String reqUrl) throws Exception{@b@		HttpPost httPost = new HttpPost(reqUrl);@b@		//设置from data@b@		if(params!=null && !params.isEmpty()){@b@			List<NameValuePair> nvps = new ArrayList<NameValuePair>();@b@			Set<String> keys = params.keySet();@b@			for(String key : keys){@b@				nvps.add(new BasicNameValuePair(key,params.get(key)));@b@			}@b@			httPost.setEntity(new UrlEncodedFormEntity(nvps, charset));@b@		}@b@		//设置header@b@		if(headers!=null && !headers.isEmpty()){@b@			Set<String> keys = headers.keySet();@b@			for(String key : keys){@b@				httPost.addHeader(key,headers.get(key));@b@			}@b@		}@b@		this.httpResponse=httpClient.execute(httPost);@b@		HttpEntity httpEntity= httpResponse.getEntity();@b@		httpStream = httpEntity.getContent();@b@		return this;@b@	}@b@	@b@	/**@b@	 * 发送一个Get请求@b@	 * @param reqUrl@b@	 * @return@b@	 * @throws Exception@b@	 */@b@	public DefaultHttp doGet(String reqUrl) throws Exception{@b@		HttpGet httpGet = new HttpGet(reqUrl);@b@		//设置header@b@		if(headers!=null && !headers.isEmpty()){@b@			Set<String> keys = headers.keySet();@b@			for(String key : keys){@b@				httpGet.addHeader(key,headers.get(key));@b@			}@b@		}@b@		httpResponse=httpClient.execute(httpGet);@b@		HttpEntity httpEntity= httpResponse.getEntity();@b@		httpStream = httpEntity.getContent();@b@		return this;@b@	}@b@	@b@	public InputStream  doGetStream(String reqUrl,int timeout) throws Exception{@b@		HttpGet httpGet = new HttpGet(reqUrl);@b@		//设置header@b@		if(headers!=null && !headers.isEmpty()){@b@			Set<String> keys = headers.keySet();@b@			for(String key : keys){@b@				httpGet.addHeader(key,headers.get(key));@b@			}@b@		}@b@		httpClient.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, timeout);  @b@		httpClient.getParams().setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, timeout);  @b@		httpResponse=httpClient.execute(httpGet);@b@		@b@		HttpEntity httpEntity= httpResponse.getEntity();@b@		httpStream = httpEntity.getContent();@b@		return httpStream;@b@	}@b@	@b@	@b@	@b@	/**@b@	 * 获取到html内容@b@	 * @return@b@	 * @throws Exception@b@	 */@b@	public String asHtml() throws Exception{@b@		return EntityUtils.toString(httpResponse.getEntity(),charset).trim();@b@	}@b@	@b@	/**@b@	 * 保存文件,保存文件必须确保在发起Http请求(执行doGet或者doPost方法)之后才能进行保存操作,@b@	 * 否则保存文件不成功.@b@	 * 注意:该方法不能够在asHtml之后调用,否则会抛出 Attempted read from closed stream.异常@b@	 * @param file@b@	 * @throws Exception@b@	 */@b@	public void save(File file) throws Exception{@b@		if(httpStream == null) throw new Exception("还未执行HTTP请求,保存文件失败");@b@		FileUtils.copyInputStreamToFile(httpStream, file);@b@	}@b@	@b@	/**@b@	 * 添加Cookie@b@	 * @param cookie@b@	 */@b@	public void addCookie(Cookie cookie){@b@		((AbstractHttpClient)httpClient).getCookieStore().addCookie(cookie);@b@	}@b@	@b@	/**@b@	 * 获取到Cookie信息@b@	 * @return@b@	 */@b@	public List<Cookie> getCookies(){@b@		return ((AbstractHttpClient)httpClient).getCookieStore().getCookies();@b@	}@b@	@b@	/**@b@	 * 发送一个Post请求@b@	 * @param reqUrl@b@	 * @param xml@b@	 * @return@b@	 * @throws Exception@b@	 */@b@	public DefaultHttp doXml(String reqUrl,String xml) throws Exception{@b@		HttpPost httPost = new HttpPost(reqUrl);@b@		StringEntity entity = new StringEntity(xml);@b@		httPost.setEntity(entity);@b@		//设置header@b@		if(headers!=null && !headers.isEmpty()){@b@			Set<String> keys = headers.keySet();@b@			for(String key : keys){@b@				httPost.addHeader(key,headers.get(key));@b@			}@b@		}@b@		this.httpResponse=httpClient.execute(httPost);@b@		HttpEntity httpEntity= httpResponse.getEntity();@b@		httpStream = httpEntity.getContent();@b@		return this;@b@	}@b@	@b@	/**@b@	 * 获取到请求返回的状态码@b@	 * @return@b@	 */@b@	public int getResponseCode(){@b@		return this.httpResponse.getStatusLine().getStatusCode();@b@	}@b@	@b@	@b@}

2、通过下面定义SSLDownLoadHttpClient类,解决上面SSLException问题

package com.xwood.craw.crawler.spider.core;@b@@b@import java.io.IOException;@b@import java.security.KeyManagementException;@b@import java.security.NoSuchAlgorithmException;@b@@b@import javax.net.ssl.SSLContext;@b@@b@import org.apache.http.HttpResponse;@b@import org.apache.http.client.config.RequestConfig;@b@import org.apache.http.client.methods.HttpGet;@b@import org.apache.http.conn.ssl.SSLConnectionSocketFactory;@b@import org.apache.http.conn.ssl.SSLContexts;@b@import org.apache.http.impl.client.CloseableHttpClient;@b@import org.apache.http.impl.client.HttpClients;@b@import org.apache.http.util.EntityUtils;@b@@b@@b@public class SSLDownLoadHttpClient{@b@	@b@    @b@    public static String executePost(String uri, String requestBody, Integer timeOut) throws NoSuchAlgorithmException, KeyManagementException {@b@       @b@//        SSLContext ctx= SSLContext.getInstance("TLSv1.2");@b@//        ctx.init(null, null, null);@b@        SSLContext ctx = SSLContexts.custom().useProtocol("TLSv1.2").build();@b@        CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(new SSLConnectionSocketFactory(ctx)).build();@b@//        HttpPost httpPost = new HttpPost(uri);@b@        HttpGet  httpGet =new HttpGet(uri);@b@        String strResult = null;@b@        try {@b@            //httpPost.setEntity(new UrlEncodedFormEntity(parameters, Consts.UTF_8));@b@//            HttpEntity httpEntity = new StringEntity(requestBody,ContentType.TEXT_XML);@b@//            httpPost.setEntity(httpEntity);@b@            /*连接超时*/@b@            if (null != timeOut) {@b@                RequestConfig requestConfig = RequestConfig.custom()@b@                        .setConnectTimeout(timeOut).setConnectionRequestTimeout(timeOut)@b@                        .setSocketTimeout(timeOut).build();@b@//                httpPost.setConfig(requestConfig);@b@                httpGet.setConfig(requestConfig);@b@            }@b@//            HttpResponse httpResponse = httpClient.execute(httpPost);@b@            HttpResponse httpResponse = httpClient.execute(httpGet);@b@            if (httpResponse.getStatusLine().getStatusCode() == 200) {@b@                strResult = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");//获得返回的结果@b@            }@b@        } catch (IOException e) {@b@            e.printStackTrace();@b@        } finally {@b@            try {@b@                httpClient.close();//释放资源@b@            } catch (IOException e) {@b@                e.printStackTrace();@b@            }@b@        }@b@        System.out.println("===="+strResult);@b@        return strResult;@b@    }@b@ @b@    @b@    public  static  void  main(String[] args) throws  Exception{@b@    	SSLDownLoadHttpClient.executePost("https://repo.maven.apache.org/maven2/abbot/abbot/0.12.3/abbot-0.12.3.pom","", 120000);@b@    }@b@@b@}

控制台打印结果

====<project>@b@  <modelVersion>4.0.0</modelVersion>@b@  <groupId>abbot</groupId>@b@  <artifactId>abbot</artifactId>@b@  <name>Abbot</name>@b@  <version>0.12.3</version>@b@</project>