想起之前有个群友推荐了这个网站,里面特别好,有闯关的性质让各位程序员来解决各种各样的问题,很多问题是大家在实际当中会遇到的。希望自己接下来会把一些有意思的题目拿出来和大家一起分享一下,如果大家有更好的解决方案也可以在下面和我进行讨论,大家共勉。
我们先来看一下题目吧:
在了解get 和post之前我们先来看看http协议吧:
HTTP协议是应用层的协议,在TCP/IP协议接收到数据之后需要通过HTTP协议来解析才可以使用。就像过去的发电报一样,电报机就相当于socket,负责选好发送的目标并将内容发出去,但是直接发过去的数据“滴滴滴”并不能直接使用(在发送前需要先编码再发送)后才能用,电报中的编码和解码就相当于网络传输中的HTTP协议。
HTTP协议中的报文结构非常重要。HTTP中保温分为请求报文和响应报文这两种类型,这两种类型都包括三部分:首航、头部和主体。
请求报文的首航是请求行,包括方法(请求类型)、URL和HTTP版本三项内容,响应请求的首行是状态行,包括HTTP版本、状态码和简短原因三项内容,其中原因可有可无。头部保存一些键值对的属性,用冒号“:”分隔。主体保存具体内容,请求报文中主要保存POST类型的参数,响应报文中保存页面要显示的结果。首行、头部和主体以及头部的各项内容用回车换行(/R/N)分隔,另外头部和主体之间多一个空行,也就是两个连续的回车换行。它们的结构大概如下:
请求报文 | 响应报文 |
---|---|
方法 URL HTTP版本/r/n | HTTP版本 状态码 简短原因/r/n |
参数1:值/r/n | 参数1:值/r/n |
参数1:值/r/n | 参数1:值/r/n |
…/r/n | …/r/n |
/r/n | /r/n |
主体 | 主体 |
请求报文
请求行
由3部分组成,分别为:请求方法、URL(见备注1)以及协议版本,之间由空格分隔
请求方法包括GET、HEAD、PUT、POST、TRACE、OPTIONS、DELETE以及扩展方法,当然并不是所有的服务器都实现了所有的方法,部分方法即便支持,处于安全性的考虑也是不可用的
协议版本的格式为:HTTP/主版本号.次版本号,常用的有HTTP/1.0和HTTP/1.1
请求头部
请求头部为请求报文添加了一些附加信息,由“名/值”对组成,每行一对,名和值之间使用冒号分隔
常见请求头如下:
请求头 | 说明 |
Host | 接受请求的服务器地址,可以是IP:端口号,也可以是域名 |
User-Agent | 发送请求的应用程序名称 |
Connection | 指定与连接相关的属性,如Connection:Keep-Alive |
Accept-Charset | 通知服务端可以发送的编码格式 |
Accept-Encoding | 通知服务端可以发送的数据压缩格式 |
Accept-Language | 通知服务端可以发送的语言 |
请求正文
可选部分,比如GET请求就没有请求正文
GET请求示例:
POST请求示例:
报文格式:
状态行
由3部分组成,分别为:协议版本,状态码,状态码描述,之间由空格分隔
状态代码为3位数字,200~299的状态码表示成功,300~399的状态码指资源重定向,400~499的状态码指客户端请求出错,500~599的状态码指服务端出错(HTTP/1.1向协议中引入了信息性状态码,范围为100~199)
这里列举几个常见的:
状态码 | 说明 |
200 | 响应成功 |
302 | 跳转,跳转地址通过响应头中的Location属性指定(JSP中Forward和Redirect之间的区别) |
400 | 客户端请求有语法错误,不能被服务器识别 |
403 | 服务器接收到请求,但是拒绝提供服务(认证失败) |
404 | 请求资源不存在 |
500 | 服务器内部错误 |
响应头部
与请求头部类似,为响应报文添加了一些附加信息
常见响应头部如下:
响应头 | 说明 |
Server | 服务器应用程序软件的名称和版本 |
Content-Type | 响应正文的类型(是图片还是二进制字符串) |
Content-Length | 响应正文长度 |
Content-Charset | 响应正文使用的编码 |
Content-Encoding | 响应正文使用的数据压缩格式 |
Content-Language | 响应正文使用的语言 |
响应示例:
HTTP-Version表示服务器HTTP协议的版本;Status-Code表示服务器发回的响应状态代码;Reason-Phrase表示状态代码的文本描述。状态代码由三位数字组成,第一个数字定义了响应的类别,且有五种可能取值。
- 1xx:指示信息–表示请求已接收,继续处理。
- 2xx:成功–表示请求已被成功接收、理解、接受。
- 3xx:重定向–要完成请求必须进行更进一步的操作。
- 4xx:客户端错误–请求有语法错误或请求无法实现。
- 5xx:服务器端错误–服务器未能实现合法的请求。
常见状态代码、状态描述的说明如下。
- 200 OK:客户端请求成功。
- 400 Bad Request:客户端请求有语法错误,不能被服务器所理解。
- 401 Unauthorized:请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用。
- 403 Forbidden:服务器收到请求,但是拒绝提供服务。
- 404 Not Found:请求资源不存在,举个例子:输入了错误的URL。
- 500 Internal Server Error:服务器发生不可预期的错误。
- 503 Server Unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复正常,举个例子:HTTP/1.1 200 OK(CRLF)。
- GET - 从指定的资源请求数据。
- POST - 向指定的资源提交要被处理的数据
GET 方法
请注意,查询字符串(名称/值对)是在 GET 请求的 URL 中发送的:
/test/demo_form.asp?name1=value1&name2=value2
有关 GET 请求的其他一些注释:
- GET 请求可被缓存
- GET 请求保留在浏览器历史记录中
- GET 请求可被收藏为书签
- GET 请求不应在处理敏感数据时使用
- GET 请求有长度限制
- GET 请求只应当用于取回数据
POST 方法
请注意,查询字符串(名称/值对)是在 POST 请求的 HTTP 消息主体中发送的:
POST /test/demo_form.asp HTTP/1.1 Host: w3schools.com name1=value1&name2=value2
有关 POST 请求的其他一些注释:
- POST 请求不会被缓存
- POST 请求不会保留在浏览器历史记录中
- POST 不能被收藏为书签
- POST 请求对数据长度没有要求
比较 GET 与 POST
下面的表格比较了两种 HTTP 方法:GET 和 POST。
GET | POST | |
---|---|---|
后退按钮/刷新 | 无害 | 数据会被重新提交(浏览器应该告知用户数据会被重新提交)。 |
书签 | 可收藏为书签 | 不可收藏为书签 |
缓存 | 能被缓存 | 不能缓存 |
编码类型 | application/x-www-form-urlencoded | application/x-www-form-urlencoded 或 multipart/form-data。为二进制数据使用多重编码。 |
历史 | 参数保留在浏览器历史中。 | 参数不会保存在浏览器历史中。 |
对数据长度的限制 | 是的。当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符)。 | 无限制。 |
对数据类型的限制 | 只允许 ASCII 字符。 | 没有限制。也允许二进制数据。 |
安全性 | 与 POST 相比,GET 的安全性较差,因为所发送的数据是 URL 的一部分。 在发送密码或其他敏感信息时绝不要使用 GET ! | POST 比 GET 更安全,因为参数不会被保存在浏览器历史或 web 服务器日志中。 |
可见性 | 数据在 URL 中对所有人都是可见的。 | 数据不会显示在 URL 中。 |
其他 HTTP 请求方法
下面的表格列出了其他一些 HTTP 请求方法:
方法 | 描述 |
---|---|
HEAD | 与 GET 相同,但只返回 HTTP 报头,不返回文档主体。 |
PUT | 上传指定的 URI 表示。 |
DELETE | 删除指定资源。 |
OPTIONS | 返回服务器支持的 HTTP 方法。 |
CONNECT | 把请求连接转换到透明的 TCP/IP 通道。 |
当然关于它们俩区别的争论大家可以去知乎搜索一下相关大神们的解答,然而他们所谈论的深度已经涉及不到本题所涉及到的了,那么我们就了解到这里吧
解题
第一种方法:
我们知道:html中的form表单也可以指定method的值
那么我们试了一下发现并不行。。。
第二种方法:
直接使用firefox浏览器的F12然后edit&resend ,(讨论区说是可行,但是由于本人平时只用过chrome的控制台,所以没有用过火狐,以后有机会换一下吧,听说装了插件的火狐 在控制台方面比谷歌浏览器要好用一点)
第三种方法:
用java 和 python 来模拟post请求进行提交, 但是前提是事先用浏览器获取到正确的cookie 并加到其中
下面给出评论区两个小伙伴的答案
import requests.adapters
import json
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
headers = {
'Accept':'*/*',
'Accept-Encoding':'gzip, deflate,br',
'Accept-Language':'zh-CN,zh;q=0.8,en;q=0.6',
'Connection':'keep-alive',
'Cookie':'啊啊啊啊啊啊啊啊啊啊啊啊啊,
'Host':'www.qlcoder.com',
'Referer':'http://www.qlcoder.com/task/7527',
'Upgrade-Insecure-Requests':'1',
'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36',
'X-Requested-With':'XMLHttpRequest'
}
datas ={'answer':'restful','_token':'3FLMMCSTsf9SnTZrVOdhtHlcYR8ZgJyOWaBZ6H7k'}
r = requests.post("http://www.qlcoder.com/task/4/solve",headers =headers,data=datas)
public static void main(String[] args) throws IOException {
String urlStr = "http://www.qlcoder.com/task/4/solve";
URL url = new URL(urlStr);
URLConnection conn = url.openConnection();
conn.setRequestProperty("Accept", "application/json, text/javascript, */*; q=0.01");
conn.setRequestProperty("Accept-Encoding", "gzip, deflate, sdch");
conn.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.8");
conn.setRequestProperty("Connection", "keep-alive");
conn.setRequestProperty("Cookie", "啊啊啊啊啊");
conn.setDoOutput(true);
conn.setDoInput(true);
PrintWriter pw = new PrintWriter(conn.getOutputStream());
pw.print("answer=restful&_token=a6F07G7gGDPGeWLOn4rTc2XAMYFi1haDdc040I0a");
pw.flush();
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = null;
while((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
}
其中上面的啊啊啊替代的就是cookie =。=
第四种方法
把ajax拷贝到Console里面在改post完美运行
这个方法非常暴力好用,找到后直接把get 替换成post 就可以了。
其实以上四种方法都是从讨论区里总结出来的,自己也没有想到另外的解决方法,希望在以后的日子里能有其他解决办法 我会更新到这里 ,如果我有什么地方写的不对 ,还请大家多多指教。