HTTP学习之使用HTTPS访问百度

序言

HTTPS是在HTTP的基础上添加了加密功能的安全办HTTP,通过在协议层使用SSL/TSL来实现数据的加密,在握手阶段,服务器会将证书和公钥传递给客户端,客户端会通过CA的公钥对证书进行认证,如果通过的话就生成一个随机数字用来做对称加密算法的秘钥,而这个秘钥会用服务器给的公钥进行加密再返回给服务器。之后客户端与服务器之间的加密就是对称加密了,因为这样性能会比公钥加密高。

更多HTTPS相关,请看Java安全通信:HTTPS与SSL

代码

用于要使用加密功能,所以此处必须使用SSLSocket,关于其用法可以看 Java SSLSocket的使用

package com.example;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class MyHttpsClient {

    public static class HTTPAddress {
        String hostAddress;
        int point = 80;

        public HTTPAddress(String hostAddress, int point) {
            this.hostAddress = hostAddress;
            this.point = point;


        }

    }

    public static void main(String[] args) {
        //百度
        String url = "https://www.baidu.com";
        getStringByUrl(url);


    }

    public static final String HTTP_HEAD = "http://";
    public static final String HTTPS_HEAD="https://";
    public static HTTPAddress getHTTPAddress(String url) {
        if (url == null || url.equals("")) {
            return null;
        }
        String head = "";
        //注意SSL的默认端口是443
        int point = 443;
        if (url.startsWith(HTTP_HEAD)) {
            url = url.substring(HTTP_HEAD.length());
        }
        if (url.startsWith(HTTPS_HEAD)) {
            url = url.substring(HTTPS_HEAD.length());
        }
        //获取域名部分
        head = url.split("/")[0];
        //如果在url中指定端口,则获取端口
        int index = head.indexOf(":");
        if (index != -1) {
            String pointStr = head.substring(index + 1).trim();
            head = head.substring(0, index);
            point = Integer.valueOf(pointStr);
        }
        try {
            //更具域名获取ip地址
            String hostAddress = InetAddress.getByName(head).getHostAddress();
            HTTPAddress httpAddress = new HTTPAddress(hostAddress, point);
            return httpAddress;
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        return null;
    }


    public static void getStringByUrl(String url) {
        try {
            HTTPAddress httpAddress = getHTTPAddress(url);
            if (httpAddress == null) {
                return;
            }
            SSLContext context = SSLContext.getInstance("SSL");
            context.init(null,null,new SecureRandom());
            SSLSocketFactory factory = context.getSocketFactory();
            SSLSocket socket = (SSLSocket) factory.createSocket(httpAddress.hostAddress, httpAddress.point);
            //   Socket socket = new Socket(httpAddress.hostAddress, httpAddress.point);
            OutputStreamWriter osw = new OutputStreamWriter(socket.getOutputStream());
            StringBuffer sb = new StringBuffer();
            //拼装请求头,注意最后需要用\r\n结尾
            sb.append("GET /  HTTP/1.1\r\n");
            sb.append("Host: " + httpAddress.hostAddress+"\r\n");
            sb.append("Connection: keep-alive\r\n");
            //最后的\r\n不可省略表示报文首部与报文主体的分隔
            sb.append("\r\n");
            osw.write(sb.toString());
            osw.flush();
            InputStream is = socket.getInputStream();
            int count = 0;
            byte[] b = new byte[8192];
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            while ((count = is.read(b)) != -1) {
                baos.write(b, 0, count);
            }
            is.close();
            baos.close();
            String result = baos.toString();
            //根据空行,分隔出报文首部,与报文主体
            String separateStr = "\r\n\r\n";
            int index = result.indexOf(separateStr);
            String headStr = result.substring(0, index);
            String contentStr = result.substring(index);
            System.out.print("head:" + headStr + "\n");
            System.out.print("content:" + contentStr + "\n");


        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

结果

这是返回的数据

这里写图片描述

我将其中的内容部分保存为一个html文件。

这里写图片描述

用Chrome打开就是这样的,除了图片以为,都正常显示,图片是没有下载。

这里写图片描述

注意事项

1.端口

SSL一般使用的是443端口

2.关于验证服务端证书

由于没有使用自己的服务端,所以直接使用默认实现就可以了。

 SSLContext context = SSLContext.getInstance("SSL");
 context.init(null,null,new SecureRandom());

3.请求格式

我用Fiddler进行抓包,找到的请求如下,注意它的请求头在资源URL的地方只有/,在Host的地方是域名且没有端口。我把自己的请求头改成这样才成功的。

这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值