利用公网实现上下班定时打卡,真香!
背景
公司一直都是每个周报上一周的考勤,上个月突然抽风让用小程程打卡,最主要解决的问题是人员必须通过微信小程序来定位后打卡(万恶的资本家,就是希望剥削更多的劳动剩余价值!),于是就萌生了通过第三方工具自动打卡的念头(作为技术汪,还能让你把我的money随便站着就挣了?我还想躺着就把钱挣了呢!!!咦?好像哪里不对劲!臭裱脸....是早上还在床上躺着呢,卡已经打了..._),经过我的一番折腾,通过抓包(
image注意,安卓目前还没发现啥好的抓包工具,之前的Charles、VNet已经抓不到了,我用同事的苹果手机ios系统安装Stream软件抓的,真鸡贼!
,补充:又发现了一款安卓抓包神器VirtualXposed+Charles可以抓包,其原理就是通过VirtualXposed虚拟机在你手机内开启一个WX应用,然后在里面操作的数据就能够绕过微信小程序的证书了
)。发现小程序里面打卡是可以通过模拟Post提交数据的方式实现打卡滴,嘿嘿,这不就有思路了?按道理可以自己写程序来模拟Post提交参数,然后部署到可以连接公网的服务器即可以实现打卡。可惜囊中羞涩,没钱买服务器。可又想白Piao。所以又折腾一番,于是有了如下的sao操作!
前提
首次进入公司小程序已经绑定个人在公司的内部账号,实际打卡时调用的地址和报文是完全一样的(不换项目组的前提下),可以直接用Postman或者Linux的curl执行提交,便能实现打卡
实现方式
方式一、利用TX云函数实现公网调用公司小程序打卡接口
方式二、利用github的Action 功能实现调用公司小程序打卡的接口
方式一、利用TX云函数
优缺点
腾讯云函数可支持定时任务,相对于github的action工作流比较准时,但是需要付费,但是不贵,有免费的额度,先用后付费模式。
原理
TX云支持使用Python脚本,利用脚本直接调用公司打卡接口,然后把打卡结果发送给自己的QQ邮箱
1)首先注册一个TX云函数
注册地址:https://console.cloud.tencent.com/scf/list?rid=1&ns=default
2)新建云函数
注册后找到云函数:
新建云函数:
自定义创建云函数:
Python脚本如下
import requests
import ssl
import json
import time
import random
import string
from datetime import datetime
from datetime import timedelta
from datetime import timezone
import smtplib
from email.mime.text import MIMEText
cronUrl = 'https://theevilcapitalists.com/xxx/zzz/saveData'
# 打卡参数20220625
parameterNew = {"key1": val1, "key1": "val2", "key3": "key3"}
payload = json.dumps(parameterNew)
header = {"Content-Type": "application/json", "Accept": "application/json;charset=UTF-8"}
# 设置服务器所需信息
# QQ邮箱服务器地址
mail_host = 'smtp.qq.com'
# QQ邮箱用户名
mail_user = '233233233@qq.com'
# 密码(部分邮箱为授权码)
mail_pass = 'XXXXXXXXXXXXX'
# 邮件发送方邮箱地址
sender = '233233233@qq.com'
# 邮件接受方邮箱地址,注意需要[]包裹,这意味着你可以写多个邮件地址群发
receivers = ['233233233@qq.com']
SHA_TZ = timezone(
timedelta(hours=8),
name='Asia/Shanghai',
)
utcNowTime = datetime.utcnow().replace(tzinfo=timezone.utc)
beijingNow = utcNowTime.astimezone(SHA_TZ)
nowDateStr = beijingNow.strftime('%Y-%m-%d %H:%M:%S');
todayStr = beijingNow.strftime('%Y%m%d');
def queryWorkDay(todayStr, header):
requests.packages.urllib3.disable_warnings()
res = requests.get(
url='https://www.mxnzp.com/api/holiday/single/' + todayStr + '?ignoreHoliday=false&app_id=AAA&app_secret=BBB',
headers=header, timeout=60, verify=False)
workDayResultJson = json.loads(res.text)
status = workDayResultJson["data"]["type"]
return status
def postDcits(cronUrl, payload, header, isWorkDay):
## 取消告警
requests.packages.urllib3.disable_warnings()
if '0' == isWorkDay:
resultJson = requests.post(cronUrl, data=payload, headers=header, timeout=60, verify=False)
return resultJson.text
else:
return 'Today is a rest day. You can have a good rest at home. You don not have to look at the evil capitalists and bow your head in front of others...What a nice day!'
def sendEmail(mail_host, mail_user, mail_pass, sender, receivers, resultText,isWorkDay):
print('start send email,date=' + nowDateStr)
# 设置email信息
# 邮件内容设置
message = MIMEText(resultText, 'plain', 'utf-8')
# 邮件主题
if '0' == isWorkDay:
message['Subject'] = '【工作日】打卡(' + nowDateStr + ')'
else:
message['Subject'] = '【休息日】打卡(' + nowDateStr + ')'
# 发送方信息
message['From'] = sender
# 接受方信息
message['To'] = receivers[0]
# 登录并发送邮件
try:
# smtpObj = smtplib.SMTP_SSL(mail_host,timeout=100)
smtpObj = smtplib.SMTP(mail_host, timeout=90)
# 连接到服务器
smtpObj.connect(mail_host, 25)
# 登录到服务器
smtpObj.login(mail_user, mail_pass)
# 发送
smtpObj.sendmail(
sender, receivers, message.as_string())
# 退出
smtpObj.quit()
except smtplib.SMTPException as e:
print('error', e) # 打印错误
def run():
##随机睡眠0-69秒
sleepTime = int(random.randint(0, 69))
print('============== start sleep ... ' + str(sleepTime) + '(s)==============')
time.sleep(sleepTime)
print('============== sleep ' + str(sleepTime) + '(s) complated==============')
print('============== start queryWorkDay ... ==============')
isWorkDay = queryWorkDay(todayStr, header)
print('============== queryWorkDay complated ==============')
print('============== start postDcits ... ==============')
resultJsonText = postDcits(cronUrl, payload, header, isWorkDay)
print('============== postDcits complated ... ==============')
print('============== start sendEmail ... ==============')
sendEmail(mail_host, mail_user, mail_pass, sender, receivers, resultJsonText,isWorkDay)
print('============== sendEmail complated ==============')
return 'complated!'
# 腾讯云函数入口
def main_handler(event, context):
return run()
配置任务执行超时时间
3)新建触发器
测试时候可以配置1分钟触发一次,后面可以删除触发器,再重新新增。此处触发器使用了cron表达式。
a.自定义cron表达式可以参考:https://www.cnblogs.com/yanghj010/p/10875151.html
,
b.在线测试可以参考:https://www.matools.com/cron/
c. 此处提供几个:
0 */1 * * * * * 每间隔1分钟执行一次
0 27 8 * * 1-5 * 每个周1-周五早上8:27执行一次
0 7 18 * * 1-5 * 每个周1-周五下午18:07执行一次
为了打卡更真实,可以在Python脚本内,随机在延迟个几十秒或者一分钟左右,不要超过太久以免本次任务执行超时。
新建触发器:
后期也可以删除触发器,并且重新新增触发器:
TX云8.png
4)部署测试
此处的Python脚本在上文中
5)查看日志
此处如果没问题的话,邮箱应该能够接收到邮件了
QQ邮件.png
方式二、利用github的Action
原理
github提供免费的Action,利用脚本直接调用公司打卡接口,然后把打卡结果发送给自己的QQ邮箱
缺点
github提供免费的Action,但是有时间偏差,
误差有时候超过几分钟,十几分钟甚至几小时
(-_-||)
1)、新创建一个公开的github仓库
此仓库一定要是公开的,因为最终的执行是需要拉取此仓库代码到ubuntu系统,进行执行。
2)里面推送一下执行脚本clock_in.sh
,此简单脚本用于打卡。
脚本clock_in.sh
如下:
#!/bin/bash
#set -eux
echo '-------------------------'
echo '打卡'
echo `date`
echo '' > result.txt
curl -H "Content-Type: application/json" -H "Connection: keep-alive" -H "Referer: https://xxx/xxxx/xxxx.html" -H "Host: xxx.xxx.com" -H "Accept-Encoding: gzip,compress,br,deflate" -A "Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML) Mobile/15E148 MicroMessenger/8.0.10(0x18009dadx) NetType/4G Language/zh_CN" -X POST -d '{"userId": 1111, "pbflag": "0","addrId":233233233, "xxxxPath": ""}' -o result.txt "https://xxxxx/clockData"
echo '-------------------------'
说明
:此脚本每次执行前都会清空result.txt里面的内容,然后curl得到的结果存入result.txt里面,后面会读取里面的内容,发送到自己的邮箱。
3)配置Actions secrets,供邮件发送
发送邮件的邮箱,需要配置发送邮件的邮箱地址和授权码,此处我用的QQ邮箱,QQ邮箱开启“POP3/SMTP服务”和“IMAP/SMTP服务”,参考:https://www.cnblogs.com/kimsbo/p/10671851.html
在github内点击项目的Settings可以配置,此处的秘钥等信息,其他用户是看不到的,放心使用。
Github9.png
Github10.png
4)配置workflow的action
点击Actions按钮,新建New workflow
里面提供了很多模板,此处创建一个自定义的workflow
填写对应的配置文件并提交,yml文件在后文
Github4.png
morning.yml
如下:
name: 'morning'
on:
#此处打卡,即推送时就触发一次,测试时候把push和schedule同时打开
push:
schedule:
此处时间配置成0:16,是因为格林威治时间比+G8区时间晚8:00,实际执行时间是 0:16 + 8:00 = 8:16
- cron: '16 0 * * 1-5'
jobs:
## 任务名称,自己随便定
morning:
runs-on: ubuntu-latest
steps:
# 首先copy git仓库到虚拟机上,然后执行
- name: 'Checkout codes'
uses: actions/checkout@v1
# 执行仓库中的脚本文件
- name: 'Run Shell'
run: bash ./clock_in.sh
# 获取格式化的日期并存入GitHub内置的环境变量中
- name: 'Get Date'
run: echo "REPORT_DATE=$(TZ=':Asia/Shanghai' date '+%Y-%m-%d %T')" >> $GITHUB_ENV
# 使用现成的发送邮箱的GitHub action来发送邮件
- name: 'Send mail'
uses: dawidd6/action-send-mail@master
with:
# 这些是发送邮件需要配置的参数,更多详细的说明请访问具体的仓库
server_address: smtp.qq.com
server_port: 465
# 这些sectret的环境变量需要配置在setting中的secret下
username: ${{ secrets.MAIL_USERNAME }}
password: ${{ secrets.MAIL_PASSWORD }}
subject: 打卡结果(${{env.REPORT_DATE}})
body: file://result.txt
to: 233233233@qq.com
from: Morning
content_type: text/html
说明
:
1.action名称叫morning,
2.job名叫morning,
3.runs-on定义了需要在哪个系统环境下运行。
4.steps定义了执行步骤,通过actions内置的用户actions/checkout@v1拉取仓库代码,然后执行./clock_in.sh的Shell代码,通过dawidd6/action-send-mail@master的用户执行邮件的发送
5.配置参考:阮一峰博文:`https://www.ruanyifeng.com/blog/2019/09/getting-started-with-github-actions.html`
5)调试运行
push时候就会立即执行一次,后面需调试,就在morning.yml
内随便更改一下,提交,然后就会执行一次,此时可以查看执行日志。
点击绿色的图标进入能看到日志明细
注意!!!!!!!!!!
免责说明
:
此博文只为学习之用,也可以提醒自己防止漏打卡
,如果你的情况刚好和笔者一样,但是把它用于非正常用途,比如哪天HR和你一起来上班,并且都迟到了,但是你的卡打了还是正常的?那就尴尬了 ̄□ ̄||(如果哪天公司要处理你了,记得提前给我说一声啊,我保证在你被处理之前,立即就把这个博文删除了!鸡贼如我)