【自动登录】Python如何实现网站自动登录案例实战
本文为自动登录系列教程的第一篇入门篇,主要讲解一下如何用Python实现简单的自动登录网站。
本次案例以zblog为例,主要模拟通过用户和密码实现登录。
环境准备
本次为模拟环境,所以我这里就用phpstudy进行模拟lnmp的环境,然后用的zblog版本是php1.7版的。
安装配置一下
随便搞个域名就开干
接下来就是下载安装包解压好,放到这里
然后打开安装链接,一顿操作进行快速的安装
用户名和密码都是admin888(经典弱密码),测试的东西怎么方便怎么来
然后打开后台链接就开始干正事啦
抓包分析
我们要想让Python可以自动登录,那么就得分析人工操作的时候,浏览器都帮我们做了哪些事情,请求了哪些链接。
因为zblog后台登录不需要验证码,这也使得我们这次的模拟登录变得简单一些。
F12打开Chrome的开发者工具,找到Network选项,然后把preserve log
勾上,这个是必须的,不然链接跳转了就看不到之前的请求了。
点击登录按钮之后就可以看到一大堆的请求而且浏览器的页面也跳转了
接下来就是看看都请求了啥呗,主要就是看前面几个php相关的请求就知道了。
第一个302跳转看到有verify字样的请求基本就可以知道是校验的,而且还是post
请求,所以我们提交的用户名和密码大概率会在这里。
看到了么,我们的用户名和密码都在这里了,看起来很傻的校验啊,明文传输密码也是厉害的。但是有第二处的密码是经过加密的,等下我们就得知道这个加密的密码是用什么玩意进行加密的。
同时我们可以看到这个请求响应体里面返回了一堆的set-cookie
,那么后续的登录就是靠这个cookie进行登录校验的。(不懂的可以复习一下cookie的作用和http协议),同时可以看到这个还localtion到了第二个链接admin/index.php?act=admin
(就是后台首页的地址)
那么基本就可以确定完成登录校验的就只有/zb_system/cmd.php?act=verify
这个链接了。所以我们接下来就是把这个链接的相关请求参数搞定就OK。
搞定请求参数
通过上面的分析,其实我们发现只有一处密码加密的地方是我们需要搞定的,其余的都是明文很简单。那么接下来我们就搞定这个加密的密码吧。
这种加密请求的基本都是通过js进行加密的,最简单快速定位的方法就是进行全局搜索(ctrl+shift+f)一下加密的字段名称,看看能不能找到。但是这个得一开始就记录好所有的链接,包括我们打开的后台登录页面的,因为很有可能这个加密就是在这个登录页面的js里面。所以我们退出重新抓包看看。
然后进行全局搜索我们要的password
字段
然后就可以找到一大堆,接下来我们要把css和jquery这些给排除掉,因为这个加密不可能是在css里面的,而jquery是第三方的dom操作库一般也不会写在里面,加密这个玩意基本都是自己写的。剩下的只有login.php
这个文件了,点击进去看看。
我们就很轻松的在这里找到了它的加密逻辑,就是简单的MD5加密,这个玩意Python也有对应的模块,轻松搞定。
当然了,为了更严谨一点,看看这个MD5是不是js默认的还是作者自己改过的,可以在控制台里面看看它的原型链(不懂略过)。
可以看到它引用的是md5.js
这玩意就是js的第三方加密,没啥好说的。最简单的就是可以直接对照密文的方式看看Python的和js生成的是否一致。
比如我们都对admin
这个字符串进行加密,它后台的加密结果是
python的加密结果是
可以看到是一模一样的,因此就可以搞定啦。
接下来就是Python模拟登录的事情了。
Python模拟登录
那么我们这里用到的是requests
模块,这个模块有一个子模块是session
也就是会话模块,这个session有啥好处呢,就是同一个session会话的话会记录下每一次请求的cookie信息,所以不需要我们进行额外的处理就可以搞定。
# -*- coding: utf-8 -*-
"""
Name: zblog
Author: brooks
Date: 2021-06-16
"""
import requests
# 新建一个会话
s = requests.session()
# 构造请求表单,也就是抓包看到的form-data里面的数据
form = {
"edtUserName": "admin",
"edtPassWord": "admin888",
"btnPost": "登录",
"username": "admin",
"password": "7fef6171469e80d32c0559f88b377245",
"savedate": 1,
}
# 发起请求
api = "http://www.wodeboke.com/zb_system/cmd.php?act=verify"
r = s.post(api, data=form)
# 打印结果
print(r.text)
然后我们就可以看到结果啦,直接帮我们跳转到后台首页了
但是这里我们的东西都是写死的,所以我们稍微封装一下代码就OK。
# -*- coding: utf-8 -*- """ Name: zblog Author: brooks Date: 2021-06-16 """ import requests from hashlib import md5 def login(s: requests.session, query: str, username: str, passwd: str): # 构造请求表单,也就是抓包看到的form-data里面的数据 form = { "edtUserName": username, "edtPassWord": passwd, "btnPost": "登录", "username": username, "password": crypt_pwd(passwd), "savedate": 1, } try: r = s.post(query, data=form) except requests.RequestException as err: print(f"login error: {err}") return return r.text def crypt_pwd(pwd: str): return md5(pwd.encode('utf-8')).hexdigest() if __name__ == '__main__': # 新建一个会话 s = requests.session() # 发起请求 api = "http://www.wodeboke.com/zb_system/cmd.php?act=verify" html = login(s, api, "admin", "admin888") # 打印结果 print(html)
这样就实现了代码的封装啦,简简单单的登录功能就做好了。
至于发布功能我们留着下次再搞吧,要去买菜做饭去了。