一、前言
因为每天晚上十点钟要求在易班中的一个轻应用进行校区定位打卡 , 但是只有一个小时 , 这个时间点作为和舍友快乐五排的时间 , 总是忘记打卡 。因此就想着做一个自动打卡的 , 挂载在云函数中 , 也不需要单独的服务器 , 每天定时运行 , 岂不是美滋滋 。
二、发现问题
首先 , 这个易班是一个手机APP , 但是我在电脑网页端查看了易班官网 , 发现就算是登录后依然不能进行打卡相关操作 , 所以只能把目标再次转回到手机APP中 , 利用手机的HttpCanary对其进行了抓包 。但是呢 , 因为高版本安卓手机的整数问题 , 打开抓包APP都不能登陆 。轻应用在易班中呈现一种站内链接跳转的方式 , 因此 , 决定先关闭抓包 , 进入APP , 在直接点击进入打卡的链接跳转 , 毕竟只用获取到用于post打卡信息的url即可 , 最后发现先进入所有打卡列表的页面 , 再进行抓包是可行的 。
通过抓包之后 , 获取到了post打卡信息的url , 发现请求头中有一个Authorization的验证 , 是一个加密信息 。

文章插图
于是对authorization加密信息进行base64的解密 , 解密完发现这个东西由三部分组成 , 前两部分只进行了base64加密 , 第三部分应该是还有别的加密 。base64解码后显示是乱码 。

文章插图
看来这条路是行不通的 。但是 , 经过试验 , 发现了打卡的轻应用在“我的”页面中是可以点击退出登录的 , 就去点了一下 , 结果跳出了登录界面 , 通过复制链接 , 发现电脑是可以打开这个登陆页面的 , 因为平时这个都是app内应用 , 所以是没有登陆的 , 看不到登录页面 。
那么有了登陆页面就很简单了啊 , 通过浏览器登陆并抓包发现 , 登陆成功后 , 有一个Ajax请求的返回信息正好是携带了token , 而且跟前面的请求头中的authorration格式是一样的 。

文章插图
发现这个就很简单了 , 只要先对这个Ajax发起post拿到token , 在用这个token取进行打卡就行了 。
然后点到post表单 , 发现登陆的密码是加密的 。查看后应该是一个MD5的加密 , 进行一个小小的逆向就可以拿到加密方法了 。

文章插图
做完这一步骤以后 , 又发现打卡的时候post的url , 后面携带了一个叫做ID的东西 。

文章插图
最后返回去之后 , 抓包发现获取打卡列表的时候 , 响应值中打卡列表中每一个打卡都有一个对应的ID , 就是打卡的时候post携带的ID 。

文章插图
那么 , 做完以上的所有操作 , 就知道了代码实现的流程了 , 首先利用逆向出的加密方法进行模拟登陆 , 获取Ajax响应结果中的token , 使用token请求获取打卡列表中对应今天的打卡ID , 利用获取到的打卡ID进行打卡操作 。
三、代码操作流程
用到的库文件
1 import execjs2 import requests3 import time4 from multiprocessing.dummy import Pool【易班校内轻应用智慧学工JS逆向、模拟登陆、每日打卡】逆向过程就不贴出来了 , 一个简单的JS调试就可以拿到逆向方法啦 。
首先就是进行模拟登陆
1 # 利用逆向得到的js文件对明文密码进行加密,传入明文密码 , 返回加密密码 2 def encrypted_password(cleartext_passwords): 3node = execjs.get() 4ctx = node.compile(open(file='./zhxgPasswordEncrypt.js', mode='r', encoding='utf-8').read()) 5function_name = 'getpwd' 6encrypted_password = ctx.call(function_name, cleartext_passwords) 7return encrypted_password 89 10 # 模拟登陆获取token,传入用户名和加密密码,返回token11 def get_token(UserName, encrypted_password):12url = ''13headers = {14'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Mobile Safari/537.36 Edg/96.0.1054.62',15}16data = https://tazarkount.com/read/{17'Password': encrypted_password,18'UserName': UserName,19}20response = requests.post(url=url, headers=headers, data=https://tazarkount.com/read/data).json()21data = https://tazarkount.com/read/response['data']22token = data['Token']23return token第二步就是进行打卡ID的获取
1 # 获取当天需要打卡的签到ID,传入authorization需要的token,返回signID 2 def get_signID(token): 3url = '' 4headers = { 5'User-Agent': 'Mozilla/5.0 (Linux; Android 10; YAL-AL00 Build/HUAWEIYAL-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36 yiban_android/5.0.7', 6'Authorization': token, 7'Platform': 'mobile', 8} 9response = requests.get(url=url, headers=headers).json()10data = https://tazarkount.com/read/response['data']11signID = data[0]['ID']12return signID第三部当然就是进行打卡啦
1 # 进行签到操作 , 传入参数signID , token,返回签到信息 2 def sign(signID, token, UserName): 3url = '' 4headers = { 5'Content-Type': 'application/x-www-form-urlencoded', 6'User-Agent': 'Mozilla/5.0 (Linux; Android 10; YAL-AL00 Build/HUAWEIYAL-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36 yiban_android/5.0.7', 7'Authorization': token, 8'Platform': 'mobile', 9}10timestamp = time.time()11format_time1 = time.strftime('%Y-%m-%d', time.localtime(timestamp))12format_time2 = time.strftime('%H:%M:%S', time.localtime(timestamp))13requests_body = {14'jwd': '',15'position': '',16'signtime': f'{format_time1}\n{format_time2}',17'id': signID,18}19response = requests.post(url=url, headers=headers, data=https://tazarkount.com/read/requests_body).json()20if'成功' in response['message']:21message = f'{UserName}晚间签到完成-->{format_time1}'22else:23message = f'{UserName}晚间签到失败-->{format_time1}'24return message最后可以利用server酱进行一个wx推送的通知 。
1 # 微信推送 , 传入参数:要推送的信息 , 推送信息的key2 def send_message(message, key):3url = 'https://sctapi.ftqq.com/' + key + '.send'4data = https://tazarkount.com/read/{5'title': message,6'desp': message,7}8requests.post(url=url, params=data)那一个宿舍的 , 可以自动打卡总不能不带上舍友吧 。所以就带上舍友们咯 。再加一个线程池吧!
1 # 完成所有操作 。传入用户名和明文密码 。2 def finish(information_dic): 3UserName = information_dic['UserName'] 4cleartext_passwords = information_dic['Password'] 5key = information_dic['key'] 6# 加密密码 7enPassword = encrypted_password(cleartext_passwords) 8# 获取token 9token = get_token(UserName, enPassword)10# 获取signID11signID = get_signID(token)12# 签到13message = sign(signID, token, UserName)14# 微信推送15send_message(message, key)16 17 18 def main(*args):19pool = Pool(5)20pool.map(finish, information_list)到此 , 所有的代码编写还有分析过程就结束了 , 最后测试没问题 , 直接挂到服务器或者云函数每天就不用自己动手签到了 。
最后把整体的代码也贴出来咯 。感谢浏览 , 因为不是正统程序员出身 , 只是出于对编程的爱好学习的 , 因此如果代码中不规范的地方还请包涵 , 也可以提给我 , 我会虚心学习的 。
1 # -*- coding: utf-8 -*-2 # @Time : 2022/1/6 21:443 # @Author : 遠方4 # @QQ:25603899315 # @File : main.py6 import execjs7 import requests8 import time9 from multiprocessing.dummy import Pool 1011 # 信息配置 12 information_list = [ 13# 自己 14{'UserName': '', 'Password': '', 'key': '', }, 15# 张三 16{'UserName': '', 'Password': '', 'key': '', }, 17# 李四 18{'UserName': '', 'Password': '', 'key': '', }, 19# 王麻子 20{'UserName': '', 'Password': '', 'key': '', }, 21 ] 222324 # 利用逆向得到的js文件对明文密码进行加密,传入明文密码 , 返回加密密码 25 def encrypted_password(cleartext_passwords): 26node = execjs.get() 27ctx = node.compile(open(file='./zhxgPasswordEncrypt.js', mode='r', encoding='utf-8').read()) 28function_name = 'getpwd' 29encrypted_password = ctx.call(function_name, cleartext_passwords) 30return encrypted_password 313233 # 模拟登陆获取token,传入用户名和加密密码,返回token 34 def get_token(UserName, encrypted_password): 35url = '' 36headers = { 37'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Mobile Safari/537.36 Edg/96.0.1054.62', 38} 39data = https://tazarkount.com/read/{ 40'Password': encrypted_password, 41'UserName': UserName, 42} 43response = requests.post(url=url, headers=headers, data=data).json() 44data = https://tazarkount.com/read/response['data'] 45token = data['Token'] 46return token 474849 # 获取当天需要打卡的签到ID,传入authorization需要的token,返回signID 50 def get_signID(token): 51url = '' 52headers = { 53'User-Agent': 'Mozilla/5.0 (Linux; Android 10; YAL-AL00 Build/HUAWEIYAL-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36 yiban_android/5.0.7', 54'Authorization': token, 55'Platform': 'mobile', 56} 57response = requests.get(url=url, headers=headers).json() 58data = https://tazarkount.com/read/response['data'] 59signID = data[0]['ID'] 60return signID 616263 # 进行签到操作 , 传入参数signID , token,返回签到信息 64 def sign(signID, token, UserName): 65url = '' 66headers = { 67'Content-Type': 'application/x-www-form-urlencoded', 68'User-Agent': 'Mozilla/5.0 (Linux; Android 10; YAL-AL00 Build/HUAWEIYAL-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36 yiban_android/5.0.7', 69'Authorization': token, 70'Platform': 'mobile', 71} 72timestamp = time.time() 73format_time1 = time.strftime('%Y-%m-%d', time.localtime(timestamp)) 74format_time2 = time.strftime('%H:%M:%S', time.localtime(timestamp)) 75requests_body = { 76'jwd': '', 77'position': '', 78'signtime': f'{format_time1}\n{format_time2}', 79'id': signID, 80} 81response = requests.post(url=url, headers=headers, data=https://tazarkount.com/read/requests_body).json() 82if'成功' in response['message']: 83message = f'{UserName}晚间签到完成-->{format_time1}' 84else: 85message = f'{UserName}晚间签到失败-->{format_time1}' 86return message 878889 # 微信推送 , 传入参数:要推送的信息 , 推送信息的key 90 def send_message(message, key): 91url = 'https://sctapi.ftqq.com/' + key + '.send' 92data = https://tazarkount.com/read/{ 93'title': message, 94'desp': message, 95} 96requests.post(url=url, params=data) 979899 # 完成所有操作 。传入用户名和明文密码 。100 def finish(information_dic):101UserName = information_dic['UserName']102cleartext_passwords = information_dic['Password']103key = information_dic['key']104# 加密密码105enPassword = encrypted_password(cleartext_passwords)106# 获取token107token = get_token(UserName, enPassword)108# 获取signID109signID = get_signID(token)110# 签到111message = sign(signID, token, UserName)112# 微信推送113send_message(message, key)114 115 116 def main(*args):117pool = Pool(5)118pool.map(finish, information_list)119 120 121 if __name__ == '__main__':122main()
- 春季老年人吃什么养肝?土豆、米饭换着吃
- 三八妇女节节日祝福分享 三八妇女节节日语录
- 老人谨慎!选好你的“第三只脚”
- 校方进行了深刻的反思 青岛一大学生坠亡校方整改校规
- 脸皮厚的人长寿!有这特征的老人最长寿
- 长寿秘诀:记住这10大妙招 100%增寿
- 春季老年人心血管病高发 3条保命要诀
- 眼睛花不花要看四十八 老年人怎样延缓老花眼
- 香槟然能防治老年痴呆症? 一天三杯它人到90不痴呆
- 老人手抖的原因 为什么老人手会抖
