文章目录
1、前言
哈喽哈喽,今天是星期6!!!愉快的一周~
最近有想写个对接学校教务系统的微信小程序,但是我搞不到现成的接口,去抓包学校官方的小程序,又没抓到,那就只有去看学校的教务系统网站了。
学校用的是正方教务系统
如下图:
值得说明的是:我们学校是分内网和外网访问教务系统的。内网登录要有专门的账号才能连接, 其在小程序中对于用户是不便的,所以决定用Python实现外网
登录正方教务系统。(能外网登录的前提就是实现了内网的登录)
2、webvpn 页面分析和登录实战效果
百度百科
:WebVPN提供基于web的内网应用访问控制,允许授权用户访问只对内网开放的web应用,实现类似VPN(虚拟专用网)的功能。
外网登录:学校webvpn登录
http://ids.cqyti.com/authserver/login?service=http%3A%2F%2Fwebvpn.cqyti.com%3A8333%2Fusers%2Fauth%2Fcas%2Fcallback%3Furl#
下面是认证首页:
登录查看其参数:
需要关注的参数:验证码先不管。
username
: 学号password
: 加密后的密码execution
: 请求的网页中
execution:√
password:√
这个密码大概找了一下,后面遇到了一个接口,它密码是没加密的,我就没有用上面这个接口了。
首先我们看这个密码:
VDHBe29XwDbfdppkXA54Y3uHvq+9WIE3TsaButGDYRv8IZ60UNO97TMtzEHP6HB5eqp3V4sEe59oRFE9h9wgQUty6PdqTcn0Qxpb7hp77LM=
初看,没看出来是什么东西 (博主是新手,见谅~) ,这样就只有一步一步地去找js。
先全局搜几个关键词试试:发现没什么作用
不慌,全局没找到,就去一个一个看js。
英文好的朋友,就会发现:encrypt
就是加密的意思,那我首先进入查看它:
emm~ 看到这里密码加密就差不多就找到了, 断点看看:右键
–Open in Sou..
选取合适的地方
进行调试分析:
网页的 js :
function getAesString(data, key0, iv0) {
key0 = key0.replace(/(^\s+)|(\s+$)/g, "");
var key = CryptoJS.enc.Utf8.parse(key0);
var iv = CryptoJS.enc.Utf8.parse(iv0);
var encrypted = CryptoJS.AES.encrypt(data, key, {
iv: iv, // 偏移量
mode: CryptoJS.mode.CBC, // CBC 加密方式
padding: CryptoJS.pad.Pkcs7 // Pkcs7 填充方式
});
return encrypted.toString();
}
function encryptAES(data, aesKey) {
if (!aesKey) {
return data;
}
var encrypted = getAesString(randomString(64) + data, aesKey, randomString(16));
return encrypted;
}
function encryptPassword(pwd0, key) {
try {
return encryptAES(pwd0, key);
} catch (e) {
}
return pwd0;
}
var $aes_chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
var aes_chars_len = $aes_chars.length;
function randomString(len) {
var retStr = '';
for (i = 0; i < len; i++) {
retStr += $aes_chars.charAt(Math.floor(Math.random() * aes_chars_len));
}
return retStr;
}
仔细看:
主要js 就是 randomString()
和 getAesString()
python中代码实现上述加密:
""""
CSDN:抄代码抄错的小牛马
"""
# pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn pycryptodome==3.9.0
# pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn PyExecJS
# from Crypto.Cipher import AES 安装成功后还报错,解决--> 先确定安装成功,再找到 crypto 的安装文件夹 ,将其改为:Crypto 大写的 C
from Crypto.Cipher import AES
import random
import base64
aes_chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678' # 48
aes_chars_len = len(aes_chars)
# 产生随机字符
def randomString(len1):
retStr = ''
for i in range(len1):
retStr += aes_chars[random.randint(0, aes_chars_len - 1)]
return retStr
pass
# 加密
def getAesString(data, key0, iv0):
data = pad(data)
key = key0.encode('utf-8')
mode = AES.MODE_CBC
iv = iv0
print('key1', key)
print('mode', mode)
print('i_v', iv.encode("utf-8"))
print('============================')
print(len(data))
# 创建加密对
AES_obj = AES.new(key, mode, iv.encode("utf-8"))
# 完成加密
AES_en_str = AES_obj.encrypt(data.encode("utf-8"))
# 用base64编码一下
AES_en_str = base64.b64encode(AES_en_str)
# 最后将密文转化成字符串
AES_en_str = AES_en_str.decode("utf-8")
return AES_en_str
pass
# 补位 必须为 16 的倍数
def pad(data):
length = 16
count = len(data)
if count < length:
add = (length - count)
data = data + ('\0' * add)
elif count > length:
add = (length - (count % length))
data = data + ('\0' * add)
return data
if __name__ == '__main__':
username = '111111111' # 学号
data = '123456' # 密码
key0 = randomString(16)
iv0 = randomString(16)
key = key0
iv = iv0
enctext = getAesString(data, key, iv)
print(enctext)
enctext2 = getAesString(enctext, key, iv)
print(enctext2)
print()
end_pass = randomString(64) + enctext2 # 最终加密的密码
print('最终的:', end_pass)
print('最终的长度:', len(end_pass))
pass
查看:
在线检验: 在线加密解密工具
再:
最后的密码就是: 随机 64 为字符 + 上面的
好! 这个接口就这样了。当时我在调试上面的接口时,找到了一个新的接口,它密码不加密就可以登录…
如下:
都是一个用户认证,进入到同一个页面。
authenticity_token
在页面页可以直接找到:
代码登录:
""""
CSDN:抄代码抄错的小牛马
"""
# 获取公钥
# http://192-168-200-87.webvpn.cqyti.com:8333/jwglxt/xtgl/login_getPublicKey.html?time=1680257350906&_=1680257350774
# 登录接口
# http://192-168-200-87.webvpn.cqyti.com:8333/jwglxt/xtgl/login_slogin.html?time=1680257303310
# ----------------------------------------------------------------------------------------------------------------------
# 获取公钥
import requests
import time
import re
import binascii
import rsa
url1 = 'http://webvpn.cqyti.com:8333/login' # get 获取 authenticity_token
url2 = 'http://webvpn.cqyti.com:8333/users/sign_in' # Post 登录到 教务系统 和学工系统选择页面
url3 = f'http://192-168-200-87.webvpn.cqyti.com:8333/jwglxt/xtgl/login_getPublicKey.html?time={
str(int(time.time() * 1000))}'
url4 = f'http://192-168-200-87.webvpn.cqyti.com:8333/jwglxt/xtgl/login_slogin.html?time={
str(int(time.time() * 1000))}'
print(url3)
print(url4)
# 外网进入教务系统的校验 学号+身份证后六位
username = '111111'
password1 = '123456'
password2 = '1234567890'
# 获取当前13位时间戳
t = str(int(time.time() * 1000))
# 创建session会话
session = requests.session()
# 设置请求头 url1 的请求头
session.headers.update({
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Cache-Control': 'max-age=0',
'Connection': 'keep-alive',
'Host': 'webvpn.cqyti.com:8333',
'If-None-Match': 'W/"f6d3997ea652f3611badf669a518a1f6"',
'Referer': 'http://webvpn.cqyti.com:8333/login',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36',
})
# 获取 authenticity_token http://webvpn.cqyti.com:8333/login
loginPage = session.get(url1)
loginPage.encoding = 'utf-8'
authenticity_token = re.search('name="authenticity_token" value="(.*?)"', loginPage.text).group(1)
# print(authenticity_token)
# 登录信息 Post 登录到 教务系统 和学工系统选择页面
Login_Data = {
'utf8': '✓',
'authenticity_token': authenticity_token,
'user[check_path]': 'login',
'user[otp_with_capcha]': 'false',
'user[double_factor]': 'false',
'user[login]': username,
'user[password]': password1,
'user[dymatice_code]': 'unknown',
'commit': '登录 Login',
}
res = session.post(url=url2, data=Login_Data) # Post 登录到 教务系统 和学工系统选择页面
print(res.status_code)
print('------------------------------------------------------------------------')
cookie_dict = requests.utils.dict_from_cookiejar(session.cookies)
cookie = res.cookies
print(session.cookies)
print()
结果:
好了,到这里我们是可以直接去登录教务系统了:
参数:
csrftoken
:
验证码没做处理,那就只剩密码了:分析
可见:
OK 了~~
python 代码实现:
""""
CSDN:抄代码抄错的小牛马
"""
import requests
import time
import re
import binascii
import rsa
# 获取当前13位时间戳
t = str(int(time.time() * 1000))
url1 = 'http://webvpn.cqyti.com:8333/login' # get 获取 authenticity_token
url2 = 'http://webvpn.cqyti.com:8333/users/sign_in' # Post 登录到 教务系统和学工系统 选择页面
# 外网进入教务系统的校验: 默认情况下--> 学号+身份证后六位 webvpn
username = '111111111'
password1 = '123456'
password2 = '1234567890'
# webvpn
def webvpn():
# 创建session会话
session = requests.session()
# 设置请求头 url1 的请求头
session.headers.update({
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Cache-Control': 'max-age=0',
'Connection': 'keep-alive',
'Host': 'webvpn.cqyti.com:8333',
'If-None-Match': 'W/"f6d3997ea652f3611badf669a518a1f6"',
'Referer': 'http://webvpn.cqyti.com:8333/login',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36',
})
# 获取 authenticity_token http://webvpn.cqyti.com:8333/login
loginPage = session.get(url1)
loginPage.encoding = 'utf-8'
authenticity_token = re.search('name="authenticity_token" value="(.*?)"', loginPage.text).group(1)
# print(authenticity_token)
# 登录信息 Post 登录到 教务系统 和学工系统 选择页面
Login_Data = {
'utf8': '✓',
'authenticity_token': authenticity_token,
'user[check_path]': 'login',
'user[otp_with_capcha]': 'false',
'user[double_factor]': 'false',
'user[login]': username,
'user[password]': password1,
'user[dymatice_code]': 'unknown',
'commit': '登录 Login',
}
res = session.post(url=url2, data=Login_Data) # 发起Post 登录到 教务系统 和学工系统选择页面
# obj = re.compile(r'<li class="col-md-3 col-sm-6 col-xs-12">.*?<a href="(?P<href>.*?)"', re.S)
# result = obj.finditer(res.text)
# lists = []
# for item in result:
# # href = item.group('href')
# # 0 教务系统 1 学工系统
# lists.append(item.group('href'))
# print(lists)
print(res.status_code)
print('------------------------------------------------------------------------')
# 查看 cookie
cookie_dict = requests.utils.dict_from_cookiejar(session.cookies)
cookie = res.cookies
# print(session.cookies)
print(cookie)
# print(cookie_dict)
print()
return cookie
# 密码 --> 加密 rsa
def get_password(pw, modulus):
weibo_rsa_e = 65537
message = str(pw).encode()
rsa_n = binascii.b2a_hex(binascii.a2b_base64(modulus))
key = rsa.PublicKey(int(rsa_n, 16), weibo_rsa_e)
encropy_pwd = rsa.encrypt(message, key)
the_enpassword = binascii.b2a_base64(encropy_pwd)
return the_enpassword
# 正方教务系统登录页面
def zfjwxt(cookie):
session = requests.session()
# xx = session.get(lists[0],cookies=cookie)
xx = session.get(url='http://192-168-200-87.webvpn.cqyti.com:8333/jwglxt/xtgl/login_getPublicKey.html?time=' + t,
cookies=cookie)
publicKey = xx.json()
print(publicKey)
# 对密码进行加密
enPassword = get_password(password2, publicKey['modulus'])
# 获取 csrftoken http://192-168-200-87.webvpn.cqyti.com:8333/jwglxt/xtgl/login_slogin.html?time=1680257303310
csrftoken_url = 'http://192-168-200-87.webvpn.cqyti.com:8333/jwglxt/xtgl/login_slogin.html?time=' + t
login_zf = session.get(csrftoken_url)
login_zf.encoding = 'utf-8'
# csrftoken = re.search('name="csrftoken" value="(.*?)"', login_zf.text).group(1)
csrftoken = re.search('name="csrftoken" value="(.*?)"', login_zf.text).group(1)
# print(login_zf)
print('------------------- csrftoken -------------------')
print(csrftoken)
print()
# 登录信息 正方教务系统登录 页面
info = {
'csrftoken': csrftoken,
'language': 'zh_CN',
'yhm': username,
'mm': enPassword,
'mm': enPassword
}
# post 提交 学号+密码 登录
res = session.post('http://192-168-200-87.webvpn.cqyti.com:8333/jwglxt/xtgl/login_slogin.html?time=' + t, info)
cookie2 = res.cookies
print(cookie2)
print("------------------- 登录中 -------------------")
if re.findall('用户名或密码不正确', res.text):
print('用户名或密码错误.....')
print()
else:
print("登陆成功")
print()
# 查询课表 其他改下参数即可
kebiao(session)
# 关闭会话
session.close()
# 查询 课表
def kebiao(session):
# session = requests.session()
# 查询 课表
# http://192-168-200-87.webvpn.cqyti.com:8333/jwglxt/kbcx/xskbcx_cxXsgrkb.html?gnmkdm=N2151&su=2020214371
data = {
'xnm': 2022,
'xqm': 12,
'kzlx': 'ck',
'xsdm': '',
}
# cookies=cookie2
kebiao = session.post(
'http://192-168-200-87.webvpn.cqyti.com:8333/jwglxt/kbcx/xskbcx_cxXsgrkb.html?gnmkdm=N2151&su=' + username,
data=data,
)
kb = kebiao.json()
print(kb)
def main():
print('程序结束...')
if __name__ == '__main__':
cookie = webvpn()
cookie2 = zfjwxt(cookie)
main()
效果:
这样就可登录进去了,这里简单的进行了课表的查询,如要进行其他信息的获取,直接session请求对应接口即可。
拜~~~ 我们下次再见 ^ _ ^