目录
1.了解HTTP协议
2.HTTP协议的报文格式
1)请求报文格式
2)响应报文格式
3)报文格式的注意事项
3.认识URL
1)分析一个具体的URL
2)URL中可省略的部分
3)关于URL encode和URL decode
4.HTTP请求(Request)
1)GET方法
2)POST方法
3)其他相关方法
5.认识请求报头(header)
6.HTTP响应(Response)
1)认识状态码(status code)
2)认识响应正文(body)
7.构造HTTP请求
1)通过form表单构造HTTP请求
2)通过ajax构造HTTP请求
8.HTTPS
1)什么是HTTPS
2)为什么引入HTTPS
3)HTTPS的工作流程
4)HTTPS传输过程
谈谈 GET 和 POST 的区别
HTTP (HyperText Transfer Protocol, 超文本传输协议) 是一种应用非常广泛的 应用层协议.
所谓“超文本”的含义,就是传输的内容不仅仅是文本(比如html,css这个就是文本),还可以是一些其他资源,比如图片,视频,音频等二进制 的数据
首行:【方法】【URL】【版本】
空行
Body:空行后面的内容为Body
首行:【版本号】【状态码】【状态码的解释】
Header:请求的属性
空行
Body:空行后面的内容Body
1.首行的内容之间有一个空格
2.请求的属性是使用冒号分割是键值对
每组属性之间使用\n分割
遇到空行表示Header部分结束
3.Body允许为空
如果Body存在,Header中会有一个Content-Length属性来标识Body的长度
4.协议格式总结
https://dict.youdao.com/result?word=1&lang=en
https:协议方案名
user:pass:登录信息,目前一般会省略
dict.youdao.com:服务器地址,此处是一个“域名”,域名会通过DNS系统解析成一个具体的IP地址
端口号:目前一般会省略,http协议默认使用80端口,https协议默认使用443端口
/result:带层次的文件路径
Word=1&lang=en:查询字符串(query string),本质是一个键值对结构,键值对之间使用&分割,键和值之间使用=分割
片段标识:此URL中省略了片段标识,片段标识主要用于页面跳转
协议名:可以省略,省略后默认为http://
ip地址/域名:在HTML中可以省略,省略后表示服务器的ip/域名与当前的HTML所属的ip/域名一致
端口号:可以省略,省略后如果是http协议,端口号自动设为80;如果是https协议,端口号自动设为443
带层次的文件路径:可以省略,省略后相当于/,有些服务器会在发现/路径的时候自动问/index。html
查询字符串:可以省略
片段标识:可以省略
像“/ ? : = &”等这样的字符,已经被URL当做特殊意义理解了,因此这些字符不能随意出现
把特殊字符,转换成转义字符 => URL encode
把转义字符,还原成原来的字符 => URL decode
构造HTTP GET请求的情况
1.直接在浏览器中输入URL
2.HTML中的link,img,a,script标签等
3.from表单
4.ajax
5.使用Java代码/其他的库
6.通过Linux下的wegt/curl
7.通过第三方工具,postman这类工具
GET请求的特点
1.首行的第一部分为GET
2.URL的query string 可以为空,也可以不为空
3.header部分有若干个键值对结构
body部分为空(也可以不为空)
构造HTTP POST请求的情况
1.form表单
2.ajxa
3.第三方工具
POST请求的特点
1.首行的第一部分为POST
2.URL的query string 一般为空(也可以不为空)
3.header部分有 若干个键值对结构
4.body部分一般不为空,body内的数据格式通过header中Content-Type指定body的长度由header中的Content-Length指定
header的整体的格式也是“键值对”结构,每个键值对占一行,键和值之间使用分号分割
1)Host:表示服务器主机的地址和端口
2)Content-Length:表示body中数据长度
3)Content-Type:表示body中的数据格式的类型
1.application/x-www-form-urlencoded:在 form 表单提交的时候会出现的数据格式类型.
2.multipart/form-data:通常用于提交图片/文件
3.application/json
4)User-Agent:字段User-Agent会将创建请求的浏览器和用户代理名称等信息传达给服务器
5)Referer:表示这个页面是从那个页面跳转过来的,如果直接在浏览器中输入URL,或直接通过收藏夹访问页面时是没有Referer的
6)Cookie:因为HTTP是无状态的协议,无法根据之前的状态进行本次的请求处理,为了保留无状态协议这个特征,于是引入了Cookie信息来控制客户端的状态,Cookie会根据从服务器端发送的响应报文内的一个叫做Set-Cookie的首部字段信息,通知客户端保存,Cookie当下次再给该服务器发送请求的时候,客户端会自动再请求报文中加入Cookie值后发送出去,服务器端发现客户端发送来的Cookie后,会去检查是哪一个客户端发送来的连接请求,对比服务器上的记录,最后得到之前的状态信息
认识请求正文(body)
1) application/x-www-form-urlencoded
2) multipart/form-data
3)application/json
200 OK:这是一个最长见的状态码,表示访问成功
404 Not Found:没有找到资源
403 Forbidden:表示访问被拒绝,有的页面通常需要用户具有一定的权限才能访问(登录后才能访问),如果用户没有登录直接访问,就容易见到403
500 Internal Server Error:服务器出现内部错误,一般是服务器的代码执行过程中遇到了一些特殊情况(服务器异常崩溃)会出现这个
302 Move temporarily:临时重定向,重定向就和呼叫转移一样(就相当于换了个手机号,别人呼叫你的旧手机号,会自动转到新手机号上)
正文的格式取决于Content-Type
text/html:body中数据格式是html
text/css:body中数据格式是css
application/JavaScript:body中数据格式是Javascript
application/json:body中数据格式是json
构造GET请求:
构造POST请求
发送GET请求
发送POST请求
通过第三方库来封装ajax
通过Java socket构造HTTP请求
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class HttpClient {
private Socket socket;
private String ip;
private int port;
public HttpClient(String ip,int port) throws IOException {
socket = new Socket(ip,port);
this.port = port;
this.ip = ip;
}
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");
// GET 不需要 body, 构造完毕
OutputStream outputStream = socket.getOutputStream();
// outputStream 是一个字节流,以字节为单位进行写入,因此需要把 StringBuilfer 转换乘byte[]
outputStream.write(request.toString().getBytes());
// 读取响应
InputStream inputStream = socket.getInputStream();
// 1M 大小的缓冲区,用来存放响应数据
byte[] buffer = new byte[1024 * 1024];
// n 表示实际上读到的字节数
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-Type: text/plain\n");
request.append("Content-Length: " + body.getBytes().length + "\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("42.192.83.143",9090);
String resp = httpClient.get("/AjaxMockServer/info");
System.out.println(resp);
// String resp = httpClient.post("/AjaxMockServer/info","这是正文");
// System.out.println(resp);
}
}
HTTPS也是一个应用层协议,是在HTTP协议的基础上引入了一个加密层(SSL/TLS)
因为HTTP是明文传输,本来要传什么,实际上就传了什么,但是一旦这样传输,在传输的过程中,被第三方截获到了,就可能造成信息泄露,于是就引入了HTTPS在HTTP基础上进行了加密,进一步的保护了用户的信息安全
明文:真正要传输的信息
密文:加密之后的消息
加密:就是把明文进行一系列变换,生成密文
解密:就是把密文在进行一系列变换,还原成明文
在这个加密和解密的过程中,往往需要一个或者多个中间的数据,辅助进行这个过程,这样的数据称为密钥
引入对称加密
对称加密其实就是通过同一个“密钥”,把明文加密成密文,并且也能把密文解密成明文
引入非对称加密
非对称加密要用到两个密钥,一个叫做“公钥”,一个叫做“私钥”
公钥和私钥是配对的,最大的缺点就是运算速度非常慢,比对称加密要慢很多
此时也有一个问题,可能在获取的公钥就是假的
解决办法:引入证书
引入证书
在客户端和服务器刚一建立连接的时候,服务器给客户端返回一个证书,这个证书包含了刚才的公钥,也包含了网站的身份信息
当客户端获取到这个证书之后,会对证书进行校检(防止证书是伪造的)
1)判断证书的有效期是否过期
2)判断证书的发布机构是否受信任
3)要验证是否被篡改:从系统中拿到该证书发布机构的公钥,得到一个hash值(称为数据摘要),设为hash1,然后计算整个证书的hash值,设为hash2,对比hash1和hash2是否相等,如果相等,则说明证书是没有被篡改过的
客户端先从服务器那边获取到证书,证书里包含了公钥
客户端对整数进行校检
客户端生成一个对称密钥,使用公钥对对称密钥进行加密,发送给服务器
服务器得到这个请求后,使用私钥解密,得到对称密钥
客户端发出后续的请求,后续的请求都是使用这个对称密钥加密的,收到的数据也都是使用这个对称密钥解密的
GET和POST之间本质上没有区别
数据位置: GET 把自定义数据放到 query string, POST 把自定义数据放到 body
语义区别: GET 一般用于"获取数据",POST 一般用于提交数据
幂等性: GET 请求一般会设计成"幂等". POST 请求一般不要求设计成"幂等"(如果多次请求得到的结果一样, 就视为请求是幂等的)
可缓存: GET 请求一般会被缓存 POST 请求一般不能被缓存