您的位置:首页 > 理论基础 > 计算机网络

HTTP学习之使用HTTPS访问百度

2016-07-13 16:19 645 查看

序言

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的地方是域名且没有端口。我把自己的请求头改成这样才成功的。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  加密 算法 服务器