用最原始的包 socket 居然可以访问网站模拟发送 POST 请求,只要发送的字符串符合 HTTP 协议,这是最大的收获。
更进一步的参考 https://www.jianshu.com/p/f196c74e72dd
import socket
input_dict = {'name':'cheng', 'age':23}
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.56.101', 8082))
模拟 POST 请求
Case1:
s.send('POST /myself_login/ HTTP/1.1\r\nHost:192.168.56.101:8082\r\nContent-Type:application/x-www-form-urlencoded\r\nusername:administartor\r\npassword:start01a\r\nConnection:close\r\n\r\n')
Case2:下面的请求中的字符串是:通过抓取 浏览器访问登录页同时输入用户名和密码时的 POST 包得来的
s.send('POST /myself_login/ HTTP/1.1\r\nHost: 192.168.56.101:8082\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:68.0) Gecko/20100101 Firefox/68.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2\r\nAccept-Encoding: gzip, deflate\r\nReferer: http://192.168.56.101:8082/myself_login/\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 34\r\nConnection: keep-alive\r\nCookie: csrftoken=uz8SRQan48GXYbidToOP7QGyDFoMTuGEiJDQiKql0b4cRB8X86OCAMIvzHzkXUZk; sessionid=3axevcp707rdia0jbiedo1dh09zaxvxe; rob_testcookie=robert\r\nUpgrade-Insecure-Requests: 1\r\n\r\nusername=administartor&password=start01a')
case3:后来发现其实不用那么多内容,只需要 Host/Content-Type/Content-Length 即可,没有 Content-Length 的话, Django 后端是不解析或解析不到 body 的(根据 send 里的内容可知 setting.py 中一定是注释掉了 django.middleware.csrf.CsrfViewMiddleware,如果打开该注释还想成功发送请求,则需要增加 \r\nX-CSRFToken: abcd\r\nCookie: csrftoken=abcd 由 Django csrf 原理可知 crsf 的值可以随意填写只要 X-CSRFToken 和 cookie 中的 csrftoken 一致即可)
s.send('POST /myself_login/ HTTP/1.1\r\nHost: 192.168.56.101:8082\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 34\r\n\r\nusername=administartor&password=start01a')
print '----------'
buffer = []
while True:
d = s.recv(1024)
if d:
buffer.append(d)
else:
break
data = ''.join(buffer)
s.close()
header, html = data.split('\r\n\r\n', 1)
print 'Response Header is:'
print header
with open('sina.html', 'wb') as f:
f.write(html)
注意当发送请求用的是 case 1 版本时:
s.send('POST /myself_login/ HTTP/1.1\r\nHost:192.168.56.101:8082\r\nContent-Type:application/x-www-form-urlencoded\r\nusername:admin\r\npassword:start01all\r\nConnection:close\r\n\r\n')
同时服务端的写法如下即从 reqeust.META 中获取用户名和密码的:
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
print 'request.body = {0}'.format(request.body)
print 'request.POST = {0}'.format(request.POST)
print 'request.META = {0}'.format(request.META)
username = request.META.get('HTTP_USERNAME')
password = request.META.get('HTTP_PASSWORD')
root@robert-Ubuntu:~# python raw_socket.py
Response Header is:
HTTP/1.0 302 FOUND
Date: Tue, 30 Jul 2019 03:09:25 GMT
Server: WSGIServer/0.1 Python/2.7.12
Vary: Cookie
X-Frame-Options: SAMEORIGIN
Content-Type: text/html; charset=utf-8
Location: http://192.168.56.101:8082/hello
name: ==robert===
Set-Cookie: sessionid=wxnc3franlzrqrx1huawdmvei9c3qhsk; expires=Tue, 13-Aug-2019 03:09:25 GMT; httponly; Max-Age=1209600; Path=/
Set-Cookie: rob_testcookie=robert; Path=/
root@robert-Ubuntu:~#
灵感来自: TCP编程