使用apache的httpcomponents中的httpclient 4.5对https进行访问

13 篇文章 0 订阅
  1. 使用maven引入httpclient ,版本4.5.4

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.2</version>
            <scope>test</scope>
        </dependency>
  2. 导出证书
    • a. 通过浏览器访问https网站导出证书
      – 在浏览器中输入https://192.168.1.120:38080/,根据提示导出证书(因为是使用docker安装的https服务,这里的38080端口就是对应的https 443端口)。
      我用的是filefox,输入地址后,会看到证书不信任提示,按照提示一步步导出,“添加例外——查看——详细信息——导出”,保存类型选择“X509含链证书(PEM)”,即后缀为.crt
      打开crt文件,选择“详细信息——复制到文件——一顿下一步”,生成.cer文件。
    • b.在mac系统里面可以直接通过钥匙链来导出.cer文件
      – 在钥匙链的种类里面选证书,然后选择 https网站的证书名字,选择菜单里面的文件菜单下的导出项目,保存成.cer文件
      这里写图片描述
  3. 将证书导入到jdk中。

    • A. 打开终端,进入$JAVA_HOME\jre\lib\security文件夹中
    • B. 使用keytools生成认证文件
      sudo keytool -import -noprompt -keystore cacerts -storepass changeit -alias terrier -file /Users/roamer/Desktop/terrier.cer 

    其中的-alias terrier 是自己设置的别名
    -file 后面要跟crt文件的全路径
    操作成功后,会提示<证书已添加到密钥库中>

    • C. 删除认证文件的命令
      sudo keytool -delete -alias terrier -keystore cacerts -storepass changeit
  4. java代码使用httpClient访问https的RESTful 服务

        package com.ninelephas.terrier;
    
        import java.io.IOException;
        import java.util.ArrayList;
        import java.util.List;
        import java.util.UUID;
    
        import org.apache.commons.httpclient.HttpException;
        import org.apache.http.NameValuePair;
        import org.apache.http.client.entity.UrlEncodedFormEntity;
        import org.apache.http.client.methods.CloseableHttpResponse;
        import org.apache.http.client.methods.HttpPost;
        import org.apache.http.conn.ssl.NoopHostnameVerifier;
        import org.apache.http.impl.client.CloseableHttpClient;
        import org.apache.http.impl.client.HttpClients;
        import org.apache.http.message.BasicNameValuePair;
        import org.apache.http.util.EntityUtils;
        import org.apache.logging.log4j.LogManager;
        import org.apache.logging.log4j.Logger;
        import org.junit.Test;
        import org.junit.runner.RunWith;
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.test.context.ContextConfiguration;
        import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
        import org.springframework.test.context.web.WebAppConfiguration;
    
        import com.fasterxml.jackson.databind.ObjectMapper;
        import com.fasterxml.jackson.core.JsonGenerator;
    
        import com.ninelephas.terrier.controller.PassportController;
        import com.ninelephas.terrier.entity.Passport;
    
        /**
         * 
         * @ClassName: PassportTester
         * @Description: http client 测试类
         * @author 徐泽宇
         * @date 2016年12月7日 下午4:17:36
         *
         */
        @RunWith(SpringJUnit4ClassRunner.class)
        @ContextConfiguration({"classpath:/META-INF/applicationContext.xml", "classpath:/META-INF/spring-mvc.xml"})
        @WebAppConfiguration
        public class PassportTester {
            /**
             * Logger for this class
             */
            private static final Logger logger = LogManager.getLogger(PassportTester.class.getName());
    
        // private static final String urlString = "http://127.0.0.1:8080/terrier";
            private static final String urlString = "https://192.168.1.120:38080";
    
    
            /**
             * 
             * checkPassword
             * 
             * @Auther 徐泽宇
             * @Date 2016年12月12日 下午6:22:36
             * @Title: checkPassword
             * @Description: 使用http协议,测试判断密码是非正确
             * @throws HttpException
             * @throws IOException
             */
            @Test
            public void checkPassword() throws Exception {
                final String url = urlString + "/passport/check_password.json";
                logger.debug("url is {}", url); //$NON-NLS-1$
                CloseableHttpClient httpClient = null;
                try {
                    HttpPost httpPost = new HttpPost(url);
                    if (url.startsWith("https")) {
                        // https访问
                        httpClient = HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
                    } else {
                        // 普通的http调用
                        httpClient = HttpClients.createDefault();
                    }
                    List<NameValuePair> nvps = new ArrayList<NameValuePair>();
                    nvps.add(new BasicNameValuePair("mobile", "1111222"));
                    nvps.add(new BasicNameValuePair("md5Password", "md5加密的密文"));
                    httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));
                    CloseableHttpResponse response = httpClient.execute(httpPost);
                    try {
                        logger.debug("调用返回状态码:{}", response.getStatusLine());
                        logger.debug("http 返回的内容是\n{}", EntityUtils.toString(response.getEntity(), "UTF-8"));
                    } finally {
                        response.close();
                    }
                } finally {
                    httpClient.close();
                }
            }
        }
  5. 注意的几个问题
    – a.一定要保证导入证书的jre就是当前调用httpClient的java类使用的jre。否则就算证书导入成功,httpClient还是访问不了https.会出现以下错误:

    javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

    可以通过查看在$JAVA_HOME\jre\lib\security\下的cacerts文件中查找-alias 指定的别名的方式来确认是否是成功导入。
    –b. 在调用httpClient的java类中,需要对HttpClient生成的时候使用语句

    httpClient = HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();

    否则会出现如下错误:

    javax.net.ssl.SSLPeerUnverifiedException: Host name '192.168.1.120' does not match the certificate subject provided by the peer (CN=joinku, OU=joinku, O=joinku, L=joinku, ST=joinku, C=joinku)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值