作者
:学Java的冬瓜
博客主页
:☀冬瓜的主页🌙
专栏
:【JavaEE】
分享
: 在满园弥漫的沉静的光芒之前,一个人更容易看到时间,并看到自己的身影。——史铁生《我与地坛》
主要内容
:构造http请求,不需要写代码直接发送http请求:地址栏输入地址,html中 img标签,script标签,link标签,a标签;需要写代码实现http请求:使用form表单,使用jquery封装后的ajax,通过java socket构造http请求,使用第三方工具postman。http加密变成https,tls加密的流程,对称加密,非对称加密,证书,TLS握手过程。
文章目录
- 一、构造HTTP请求
- 1、form表单
- 2、使用jQuery封装ajax后提供的api
- 3、通过 Java socket 构造 HTTP 请求
- 4、第三方工具:postman
- 二、HTTPS
- 1、HTTP和HTTPS的区别
- 2、SSL/TLS加密流程
- 2.1、对称加密
- 2.2、非对称加密
- 2.3、证书
- 2.4、TLS握手过程
一、构造HTTP请求
不需要写代码直接发送http请求的方法:
1> 在浏览器地址栏输入url,回车
2> 在html中的标签 link script img a等
下面是需要写代码来完成http请求的方式:
1、form表单
<!-- 构造GET或POST请求 -->
<form action="http://abcdef.com/myPath" method="GET"> <!--或者post-->
<input type="text" name="userId">
<input type="text" name="classId">
<input type="submit" value="提交">
</form>
2、使用jQuery封装ajax后提供的api
ajax的全称是
Asynchronous JavaScript and XML
,实现异步处理,synchronous是同步。
同步请求时,浏览器需要等待收到响应才能继续执行下面的内容,而异步在发送请求后可以直接往下执行,等响应来了,再通过触发代码执行特定的代码。
实现异步一般需要多线程/IO多路复用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 先引入jquery -->
<script src="./blog/js/jquery.min.js"></script>
<script>
// jquery中$是一个全局对象,jQuery中的api都是以$的方式引出的,只有一个参数,是一个js对象,就是{}表示的键值对
$.ajax(
{
type: 'get',
url: 'http://www.baidu.com/?studentName=lihua&password=123',
// 此处success声明了一个回调函数,当服务器响应给浏览器时,就会执行这个回调函数,同时正是这个回调实现了异步
success: function(data){
console.log("浏览器收到服务器的响应, 调用success函数");
}
}
);
console.log("发送请求后,浏览器立即执行后续代码");
</script>
</body>
</html>
- 从上图中发现,是先执行回调函数下面的代码,浏览器收到服务器发送的响应后,才触发执行的success方法。体现了异步的处理方式。
- 与form表单相比,ajax功能更强
1> 支持put,delete等方法
2> ajax发送的请求可以根据需求,灵活设置 header
3> ajax 发送的请求的 body也是可以灵活设置的。
3、通过 Java socket 构造 HTTP 请求
所谓的 “发送 HTTP 请求”, 本质上就是按照 HTTP 的格式往 TCP Socket 中写入一个字符串.
所谓的 “接受 HTTP 响应”, 本质上就是从 TCP Socket 中读取一个字符串, 再按照 HTTP 的格式来解析.
我们基于 Socket 的知识, 完全可以构造出一个简单的 HTTP 客户端程序, 用来发送各种类型的 HTTP 请求.
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class HttpClient {
private Socket socket;
private String ip;
private int port;
public HttpClient(String ip, int port) throws IOException {
this.ip = ip;
this.port = port;
socket = new Socket(ip, port);
}
public String get(String url) throws IOException {
StringBuilder request = new StringBuilder();
// 构造首行
request.append("GET " + url + " HTTP/1.1\n");
// 构造 header
request.append("Host: " + ip + ":" + port + "\n");
// 构造 空行
request.append("\n");
// 发送数据
OutputStream outputStream = socket.getOutputStream();
outputStream.write(request.toString().getBytes());
// 读取响应数据
InputStream inputStream = socket.getInputStream();
byte[] buffer = new byte[1024 * 1024];
int n = inputStream.read(buffer);
return new String(buffer, 0, n, "utf-8");
}
public String post(String url, String body) throws IOException {
StringBuilder request = new StringBuilder();
// 构造首行
request.append("POST " + url + " HTTP/1.1\n");
// 构造 header
request.append("Host: " + ip + ":" + port + "\n");
request.append("Content-Length: " + body.getBytes().length + "\n");
request.append("Content-Type: text/plain\n");
// 构造 空行
request.append("\n");
// 构造 body
request.append(body);
// 发送数据
OutputStream outputStream = socket.getOutputStream();
outputStream.write(request.toString().getBytes());
// 读取响应数据
InputStream inputStream = socket.getInputStream();
byte[] buffer = new byte[1024 * 1024];
int n = inputStream.read(buffer);
return new String(buffer, 0, n, "utf-8");
}
public static void main(String[] args) throws IOException {
HttpClient httpClient = new HttpClient("www.baidu.com", 80);
String resp = httpClient.get("/index.html");
System.out.println(resp);
//HttpClient httpClient = new HttpClient("42.192.83.143", 8080);
//String getResp = httpClient.get("/AjaxMockServer/info");
//System.out.println(getResp);
//String postResp = httpClient.post("/AjaxMockServer/info", "this is
body");
//System.out.println(postResp);
}
}
代码运行结果(VSCode):
4、第三方工具:postman
1> 下载,安装,注册登录,创建个人工作空间后,点下图+号创建一个标签页,用于构造请求
2> 自定义构造请求,可以修改各种属性
二、HTTPS
1、HTTP和HTTPS的区别
HTTPS在HTTP的基础上,做了这几个改造:
1> 默认端口http是80,HTTPS是443;
2> HTTPS使用SSL/TLS加密,实现数据传输的安全性 ;
3> 使用数字证书验证,来验证网站的身份,确保用户访问的是真实的网站。
以前只使用http时,网费不足的时候就会在浏览网页收到互联网服务提供商(isp)的弹窗提示,现在HTTPS流行后,网费不足就没有提示了,而是直接断网。因为HTTPS对网络传输提供了加密,运营商设备无法再对浏览器端发送到服务器端的数据进行解析,也就无法提醒了,从而也解决了运营商劫持的问题。下面我们来看看SSL/TLS给HTTP加密的过程:
2、SSL/TLS加密流程
SSL是TLS的前身,它们都是加密安全协议,现在绝大部分浏览器都不支持SSL,而是支持TLS。
2.1、对称加密
举个例子:
- 在上述场景中,同一个密钥,既可以用来加密,又可以用来解密,双方之间都只通过这个密钥进行加密解密,这样的方式叫做对称加密。
- 但是,对称加密的密钥如果被第三方知道,就很容易破解了。那么就引入了我们的对称加密,从而把密钥安全传输。
2.2、非对称加密
1> 非对称加密理解:
- 对称加密中引入了公钥和私钥。如果数据用公钥加密,就只能用私钥解密;如果数据用私钥加密,就只能用公钥解密。
- 应用到客户端和服务端时,服务器拥有成对的公钥和私钥,公布自己的公钥让客户端知道,而私钥只有服务器端自己知道。
客户端使用服务器公布的公钥进行数据加密 传输数据给服务端,服务端使用只有自己知道的私钥解密。这样的非对称加密也叫公钥加密。 - 引入非对称加密后,客户端可以用服务器端给的公钥对 数据传输的方式(比如使用倒念) 进行加密,这个数据只有服务器端的 私钥才能解密,解密后就可以进行对称加密(后续进行对称加密是为了传输效率)。就达到了 安全传输 对称密钥 的目的,不再是对称加密中,唯一的密钥被第三方知道的情况。
2> 通过非对称加密(公钥加密,私钥解密)的方式,可以让 对称密钥 安全的发送到服务端,但是还存在一种问题,第三方虽然不知道服务端的私钥,但是是否依旧可以获取数据呢?答案是可以的,请看下图:
在上图中,黑客就作为中间的联系人,进行"两头骗"的操作,怎么解决这个问题?加证书!
2.3、证书
客户端如何认证证书是否被修改?
- 认证机构也有一组公钥和私钥,私钥用来加密hash值得到签名,公钥是公布给客户端的。
- 当客户端向服务器申请公钥时,服务器会把证书一并发给客户端。客户端可以使用认证机构提供的公钥对证书的签名进行解密,这里使用一种hash算法得到hash1,然后自己用同样的hash算法对其它字段进行计算得到hash2,如果hash1和hash2一样就代表证书未被修改过。
- 引入证书后,首先黑客不知道认证机构的私钥,无法对服务端证书的签名进行解密,也就无法篡改证书;其次,黑客只要一修改证书上对应的颁发机构或服务器公钥,客户端这里计算得到的hash1和hash2就不再相同。
- 所以,引入证书后,就保证了黑客无法在中间使用自己的公钥和私钥进行"两头骗"的行为。但是如果黑客把证书也一并替换了呢?
黑客通过欺骗 证书颁发机构(CA)或者攻击 CA的系统来获得有效证书,这种情况叫做 “CA欺骗攻击”,但是由于证书颁发机构有严格的审核程序和安全措施,黑客获取证书颁发机构的有效证书的概率很小,并且浏览器和操作系统也会定期更新黑名单,将已经被证实为不安全的证书加入其中,以保护用户受此类攻击。
黑客无法获取到证书,自然就无法使用自己的证书进行替换了!
2.4、TLS握手过程
TCP三次握手后,客户端与服务器建立连接,以确保双方的通信是可靠的。在TCP连接建立之后,客户端和服务器进行TLS握手以建立安全通信。下面是TLS握手的过程: