• httpclient3.1跳过ssl验证


    原来的老项目调用一个Http的服务,最近http的服务调整成了https,因此需要调整一下,网上大部分都是4.5以上版本,3.1版本处理方法比较少,因此记录一下

    一、实现两个类

    1.MyX509TrustManager

    1. import java.security.cert.CertificateException;
    2. import java.security.cert.X509Certificate;
    3. import javax.net.ssl.X509TrustManager;
    4. public class MyX509TrustManager implements X509TrustManager {
    5. /* (non-Javadoc)
    6. * @see javax.net.ssl.X509TrustManager#checkClientTrusted(java.security.cert.X509Certificate[], java.lang.String)
    7. */
    8. public void checkClientTrusted(X509Certificate[] arg0, String arg1)
    9. throws CertificateException {
    10. }
    11. /* (non-Javadoc)
    12. * @see javax.net.ssl.X509TrustManager#checkServerTrusted(java.security.cert.X509Certificate[], java.lang.String)
    13. */
    14. public void checkServerTrusted(X509Certificate[] arg0, String arg1)
    15. throws CertificateException {
    16. }
    17. /* (non-Javadoc)
    18. * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
    19. */
    20. public X509Certificate[] getAcceptedIssuers() {
    21. return null;
    22. }
    23. }

    2.MySecureProtocolSocketFactory

    项目使用的jdk版本是1.8,jdk版本默认协议需要指定一下,因此SSLContext context = SSLContext.getInstance("TLSv1.2");

    1. import java.io.IOException;
    2. import java.net.InetAddress;
    3. import java.net.Socket;
    4. import java.net.UnknownHostException;
    5. import javax.net.ssl.SSLContext;
    6. import javax.net.ssl.TrustManager;
    7. import org.apache.commons.httpclient.ConnectTimeoutException;
    8. import org.apache.commons.httpclient.HttpClientError;
    9. import org.apache.commons.httpclient.params.HttpConnectionParams;
    10. import org.apache.commons.httpclient.protocol.ControllerThreadSocketFactory;
    11. import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
    12. public class MySecureProtocolSocketFactory implements SecureProtocolSocketFactory {
    13. //添加一个属性,主要目的获取ssl跳过验证
    14. private SSLContext sslContext = null;
    15. /**
    16. * Constructor for MySecureProtocolSocketFactory.
    17. */
    18. public MySecureProtocolSocketFactory() {
    19. }
    20. /**
    21. * 创建一个获取SSLContext的方法,导入MyX509TrustManager进行初始化
    22. * @return
    23. */
    24. private static SSLContext createEasySSLContext() {
    25. try {
    26. SSLContext context = SSLContext.getInstance("TLSv1.2");
    27. context.init(null, new TrustManager[] { new MyX509TrustManager() },
    28. null);
    29. return context;
    30. } catch (Exception e) {
    31. throw new HttpClientError(e.toString());
    32. }
    33. }
    34. /**
    35. * 判断获取SSLContext
    36. * @return
    37. */
    38. private SSLContext getSSLContext() {
    39. if (this.sslContext == null) {
    40. this.sslContext = createEasySSLContext();
    41. }
    42. return this.sslContext;
    43. }
    44. //后面的方法基本上带入相关参数
    45. /*
    46. * (non-Javadoc)
    47. *
    48. * @see org.apache.commons.httpclient.protocol.ProtocolSocketFactory#createSocket(java.lang.String,
    49. * int, java.net.InetAddress, int)
    50. */
    51. public Socket createSocket(String host, int port, InetAddress clientHost,int clientPort) throws IOException, UnknownHostException {
    52. return getSSLContext().getSocketFactory().createSocket(host, port,clientHost, clientPort);
    53. }
    54. /*
    55. * (non-Javadoc)
    56. *
    57. * @see org.apache.commons.httpclient.protocol.ProtocolSocketFactory#createSocket(java.lang.String,
    58. * int, java.net.InetAddress, int,
    59. * org.apache.commons.httpclient.params.HttpConnectionParams)
    60. */
    61. public Socket createSocket(final String host, final int port,final InetAddress localAddress, final int localPort,
    62. final HttpConnectionParams params) throws IOException,UnknownHostException, ConnectTimeoutException {
    63. if (params == null) {
    64. throw new IllegalArgumentException("Parameters may not be null");
    65. }
    66. int timeout = params.getConnectionTimeout();
    67. if (timeout == 0) {
    68. return createSocket(host, port, localAddress, localPort);
    69. } else {
    70. return ControllerThreadSocketFactory.createSocket(this, host, port,localAddress, localPort, timeout);
    71. }
    72. }
    73. /*
    74. * (non-Javadoc)
    75. *
    76. * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int)
    77. */
    78. public Socket createSocket(String host, int port) throws IOException,UnknownHostException {
    79. return getSSLContext().getSocketFactory().createSocket(host, port);
    80. }
    81. /*
    82. * (non-Javadoc)
    83. *
    84. * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean)
    85. */
    86. public Socket createSocket(Socket socket, String host, int port,boolean autoClose) throws IOException, UnknownHostException {
    87. return getSSLContext().getSocketFactory().createSocket(socket, host,port, autoClose);
    88. }
    89. }

    最后声明MySecureProtocolSocketFactory加入Protocol就可以了。                                                  

    1. //声明
    2. ProtocolSocketFactory fcty = new MySecureProtocolSocketFactory();
    3. //加入相关的https请求方式
    4. Protocol.registerProtocol("https", new Protocol("https", fcty, 443));
    5. //发送请求
    6. org.apache.commons.httpclient.HttpClient httpclient = new org.apache.commons.httpclient.HttpClient();
    7. GetMethod httpget = new GetMethod(url);
    8. System.out.println("======https的服务地址url:" + url);
    9. try {
    10. httpclient.executeMethod(httpget);
    11. return httpget.getResponseBodyAsString();
    12. } catch (Exception ex) {
    13. ex.printStackTrace();
    14. throw new Exception(ex.getMessage());
    15. } finally {
    16. httpget.releaseConnection();
    17. }

    实现完后自信满满重新打包更新上正式环境,结果报错了。。。
     

    1. javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: Certificates do not conform to algorithm constraints
    2. at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    3. at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1946)
    4. at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:316)
    5. at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:310)
    6. at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1639)
    7. at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:223)
    8. at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1037)
    9. at sun.security.ssl.Handshaker.process_record(Handshaker.java:965)
    10. at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1064)
    11. at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367)

    百度一下这个问题,证书不符合算法约束,基本都是修改配置文件$JAVA_HOME/jre/lib/security/java.security,但是项目是docker部署的,jdk用的是docker里面的,外面服务器里的jdk版本都是11,那每次更新服务都得手动改配置也太麻烦了吧。。。

    ===================================================================

    后面找到一篇文章,修改前面的实现类,把自己实现的类改写成继承新的抽象类:X509ExtendedTrustManager即可,代码如下:

    1. //public class MyX509TrustManager implements X509TrustManager {
    2. public class MyX509TrustManager extends X509ExtendedTrustManager {
    3. //实现方法,所有方法都是空方法
    4. }

    再次更新代码,问题解决!

    参考:httpclient 3.1跳过https请求SSL的验证_鼓逗猫柠的博客-CSDN博客
    https://www.cnblogs.com/flyingeagle/articles/7508207.html

     

  • 相关阅读:
    持久与速度 鱼和熊掌 MySQL怎么去兼得
    分布式架构在云计算平台中的应用及优缺点
    在Boss直聘上投简历时,怎样保证有新消息时能及时收到
    Golang PDF转图片 拼接长图 压缩PDF及图片 输出JPEG
    MyBatis基于XML的详细使用-参数、返回结果 处理
    4.mybatis 高级结果查询
    初学者如何学习键盘编程
    码率vs.分辨率,哪一个更重要?
    华为机考入门python3--(17)牛客17- 坐标移动
    排错-关于clion not found visual studio 的问题
  • 原文地址:https://blog.csdn.net/kalifor/article/details/132871911