【置顶】疫情期间自动健康打卡暨CAS单点登录认证实践
[2020.3.11 update]
插播广告:各位找工作/找实习的小伙伴,可以内推商汤科技(SenseTime)各种岗位(开发、CV研究员、项目管理、产品经理 and so on~),欢迎踊跃提交简历~
p.s. 我作为一个后端程序员,写的前端代码(emmm,网页post,get这些就算是前端吧)确实很菜很辣鸡,请见谅
代码实现了统一身份认证系统的CAS SSO登录,以及健康打卡表单自动填写,然后邮件发送打卡结果
邮件那个sendmail.py我就不发出来了,网上一搜一大把,我也是网上搜的orz
耗时一整天,终于把它写完了!
初次学习使用CAS认证,目前的代码只保证了功能可用,但还有很多不足。例如,没有有效利用session与cookie,只能每次登录重新获取。
注:自动打卡的前提是你有一台服务器或者24小时开机的电脑,设置定时执行脚本(Linux crontab)
Python代码
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
实现疫情期间每天自动打卡
Created on 2020-03-10 23:10
@author: Zhang Jiawei
"""
import requests
import lxml.html
import re
import json
import random
import time
import traceback
headers = {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "zh-CN",
"Cache-Control": "max-age=0",
"Connection": "keep-alive",
"Content-Type": "application/x-www-form-urlencoded",
"Cookie": "MESSAGE_TICKET=%7B%22times%22%3A0%7D; ",
"Host": "cas.hrbeu.edu.cn",
"Referer": "https://cas.hrbeu.edu.cn/cas/login?service=http%3A%2F%2Fjkgc.hrbeu.edu.cn%2Finfoplus%2Flogin%3FretUrl%3Dhttp%253A%252F%252Fjkgc.hrbeu.edu.cn%252Finfoplus%252Fform%252FJSXNYQSBtest%252Fstart",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362"
}
data = {
"username":"******", ## 用户名
"password":"******" ## 密码
}
def findStr(source, target):
return source.find(target) != -1
title = ""
msg = ""
try:
#get
url_login = 'https://cas.hrbeu.edu.cn/cas/login?service=http%3A%2F%2Fjkgc.hrbeu.edu.cn%2Finfoplus%2Fform%2FJSXNYQSBtest%2Fstart'
# print ("begin to login ..")
sesh = requests.session()
req = sesh.get(url_login)
html_content = req.text
#post
login_html = lxml.html.fromstring(html_content)
hidden_inputs=login_html.xpath(r'//div[@id="main"]//input[@type="hidden"]')
user_form = {x.attrib["name"] : x.attrib["value"] for x in hidden_inputs}
user_form["username"]=data['username'];
user_form["password"]=data['password'];
user_form["captcha"]='';
user_form["submit"]='登 录';
headers['Cookie'] = headers['Cookie'] + req.headers['Set-cookie']
req.url = f'https://cas.hrbeu.edu.cn/cas/login;jsessionid={req.cookies.get("JSESSIONID")}?service=http%3A%2F%2Fjkgc.hrbeu.edu.cn%2Finfoplus%2Fform%2FJSXNYQSBtest%2Fstart'
response302 = sesh.post(req.url, data=user_form, headers=headers)
casRes = response302.history[0]
# print("******************* ", findStr(casRes.headers['Set-Cookie'],'CASTGC'))
#get
jkgc_response = sesh.get(response302.url)
#post
headers['Accept'] = '*/*'
headers['Cookie'] = jkgc_response.request.headers['Cookie']
headers['Host'] = 'jkgc.hrbeu.edu.cn'
headers['Referer'] = jkgc_response.url
jkgc_html = lxml.html.fromstring(jkgc_response.text)
csrfToken = jkgc_html.xpath(r'//meta[@itemscope="csrfToken"]')
csrfToken = csrfToken.pop().attrib["content"]
jkgc_form = {
'idc': 'JSXNYQSBtest',
'release': '',
'csrfToken': csrfToken,
'formData': {
'_VAR_URL': jkgc_response.url,
'_VAR_URL_Attr': {
'ticket': re.match(r'.*ticket=(.*)', jkgc_response.url).group(1)
}
}
}
jkgc_form['formData'] = json.dumps(jkgc_form['formData'])
jkgc_url = 'http://jkgc.hrbeu.edu.cn/infoplus/interface/start'
response3 = sesh.post(jkgc_url, data=jkgc_form, headers=headers)
#get
form_url = json.loads(response3.text)['entities'][0]
form_response = sesh.get(form_url)
#post
headers['Accept'] = 'application/json, text/javascript, */*; q=0.01'
headers['Referer'] = form_url
headers['X-Requested-With'] = 'XMLHttpRequest'
submit_url = 'http://jkgc.hrbeu.edu.cn/infoplus/interface/doAction'
submit_html = lxml.html.fromstring(form_response.text)
csrfToken2 = submit_html.xpath(r'//meta[@itemscope="csrfToken"]')
csrfToken2 = csrfToken2.pop().attrib["content"]
submit_form = {
'actionId': '1',
'boundFields': 'fieldCXXXdqszdjtx,fieldCXXXjtgjbc,fieldGLJL,fieldMQJCRxh,fieldCXXXsftjhb,......', ## 表单数据需要自己先手动执行一遍然后粘贴过来
'csrfToken': csrfToken2,
'formData': r'{"fieldCXXXsftjhbs":"","fieldCXXXsftjhb":"2",......', ## 表单数据需要自己先手动执行一遍然后粘贴过来
'lang': 'zh',
'nextUsers': '{}',
'rand': str(random.random() * 999),
'remark': '',
'stepId': re.match(r'.*form/(\d*?)/',form_response.url).group(1),
'timestamp': str(int(time.time()+0.5))
}
response_end = sesh.post(submit_url, data=submit_form, headers=headers)
## 表单填写完成,返回结果
print('表单地址: ', form_response.url)
print('表单状态: ', response_end.text)
title = f'打卡成功<{submit_form["stepId"]}>'
msg = '表单地址: ' + form_response.url + '\n\n表单状态: ' + response_end.text
except:
err = traceback.format_exc()
print('报错信息: \n', err)
title = '打卡失败!!!'
msg = '报错信息: \n' + err
finally:
## 发送邮件
import sendmail ## 这个是普通.py文件,不是Python库
sendmail.sendmail(title, msg)
参考资料
- PYTHON 实现CAS服务器认证:https://blog.csdn.net/seu_04004414/article/details/81661668 or http://www.freesion.com/article/225192597/
- CAS单点登录原理(包含详细流程,讲得很透彻,耐心看下去一定能看明白!):https://blog.csdn.net/ban_tang/article/details/80015946
- 利用Python requests库实现cas认证:https://www.cnblogs.com/cherryjing/p/9626277.html
初夏阳光
虽然不大懂 py 但是调试完了能用,学长代码真香 2333
好像是辣个认证开了代理的话就不好使。Traceback 会报 http.client.RemoteDisconnected urllib3.exceptions.MaxRetryError requests.exceptions.ProxyError 这样的。
(顺便请问我可以把调试完的代码发到我的博客吗?
zjw1111
可以转发。你说的代理指的是什么代理?
初夏阳光
我用的是 Clash 那个,设置是按规则代理非全局,报错显示请求好像是走我的 127.0.0.1:7890 出去的。