Code Bye

有证书的https SSLException bad_record_mac

用java实现抓取厦门社保,有用户名、密码等必须参数,地址是https://app.xmhrss.gov.cn/wcm/servlet/FirstServlet

通过浏览器可以正常访问,但是用java访问报异常:

javax.net.ssl.SSLException: Received fatal alert: bad_record_mac
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
	at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1959)
	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1077)
	at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323)
	at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:275)
	at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:254)
	at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:123)
	at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:318)
	at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:363)
	at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:219)
	at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)
	at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:86)
	at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
	at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
	at com.hisun.crawler.util.insurance.fujian.XiaMen_IS.getVerficationCode(XiaMen_IS.java:338)
	at com.hisun.crawler.util.insurance.fujian.XiaMen_IS.loginCheck(XiaMen_IS.java:291)
	at com.hisun.crawler.util.insurance.fujian.XiaMen_IS.crawlerInsuranceBasic(XiaMen_IS.java:83)
	at com.hisun.crawler.util.insurance.fujian.XiaMen_IS.main(XiaMen_IS.java:69)

还没到登录,在下载验证码的时候已经报异常了,代码如下:
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class XiaMen_IS
{

	public static void main(String[] args)
	{
		crawler();
	}

	// 信息抓取
	public static void crawler()
	{
		try
		{

			CloseableHttpClient cbHttpClient = createSSLInsecureClient();
			getVerficationCode(cbHttpClient);
		} catch (Exception e)
		{
			System.out.println("---厦门社保抓取失败---");
		}
	}

	// 获取验证码
	private static String getVerficationCode(CloseableHttpClient cbHttpClient) throws Exception
	{
		try
		{
			String url = "https://app.xmhrss.gov.cn/wcm/servlet/VCodeServlet";// 验证码地址
			HttpGet get = new HttpGet(url);
			HttpResponse response = cbHttpClient.execute(get);// 报异常
			// 获取验证码字节数组
			byte data[] = EntityUtils.toByteArray(response.getEntity());

		} catch (Exception e)
		{
			System.out.println("厦门社保下载验证码异常:");
			e.printStackTrace();
			throw e;
		}

		return null;
	}

	// client工具函数,信任对方(https)所有证书
	public static CloseableHttpClient createSSLInsecureClient()
	{
		try
		{
			// 创建安全套接字对象
			SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy()
			{
				// 信任所有
				public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException
				{
					return true;
				}
			}).build();
			// 获取分层tls/ssl连接
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
			return HttpClients.custom().setSSLSocketFactory(sslsf).build();
		} catch (KeyManagementException e)
		{
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e)
		{
			e.printStackTrace();
		} catch (KeyStoreException e)
		{
			e.printStackTrace();
		}
		return HttpClients.createDefault();
	}

}


SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
改为
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,new String[] {“SSLv3”}, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());

亲测已经可以把验证码下载下来了。

引用 2 楼 chenjing0320 的回复:


SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
改为
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,new String[] {“SSLv3”}, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());

亲测已经可以把验证码下载下来了。

报语法错误

引用 3 楼 liangtu33 的回复:
Quote: 引用 2 楼 chenjing0320 的回复:


SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
改为
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,new String[] {“SSLv3”}, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());

亲测已经可以把验证码下载下来了。

报语法错误

httpclient用的什么版本?
我用4.4运行的,org.apache.http.conn.ssl.SSLConnectionSocketFactory。

httpclient-4.3.4.jar

200分
我又下了个httpclient-4.3.4.jar

改成
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,new String[] {“SSLv3”}, null, null);
就可以了啊


CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明有证书的https SSLException bad_record_mac