# Python深信服校园网智能登录 **Repository Path**: KcanyueL/szy_login ## Basic Information - **Project Name**: Python深信服校园网智能登录 - **Description**: Python自动化 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2022-12-08 - **Last Updated**: 2024-04-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: Python, 自动化, 校园网, 登陆 ## README ## 汕职院校园网智能登录 就本校校园网来说,每次或者每天用之前都需要打开浏览器进行账号密码的认证登陆才能正常使用网络,而且如果使用对象是服务器这种需要24小时保持有网的,那更是麻烦,因为认证会过期,过期了就需要重新登录,导致一系列繁琐事情,为了解决这个问题,我基于Python开发了汕职院校园网智能登录,下面是对整个程序实现以及运行流程的分析: 首先,分析校园网登陆过程: 连接上校园网--打开浏览器--输入账号密码点击登录 因此,从输入账号密码点击登录这一步我们可以看出是通过**http协议的post请求向服务器发送了from表单进行验证,那么我们可以通过程序来模拟浏览器发送post请求** 我们需要用到**requests**这个包中的**post**方法: ![输入图片说明](.idea/image.png) 我们需要输入三个参数,分别是请求地址url,from表单数据data,请求头header,这些参数可以从浏览器的登录页面获取用web开发者工具获取: ![输入图片说明](.idea/image2.png) ![输入图片说明](.idea/image3.png) 代码如下: ![输入图片说明](.idea/image5.png) ![输入图片说明](.idea/image6.png) 如此我们把程序跑起来就可以直接模拟登录校园网,基本原理即为如此,但是本校的校园网对data表单传递的参数有特殊的处理,所以接下来我们重点分析data里的内容,分析可得: ![输入图片说明](.idea/image7.png) 需要重点关注的是pwd与rc4Key这两个字段,比如我们在页面上输入的密码明明是20030227但是到了被接收入data表单前显然经过加密处理变成上图的未知字符串,但通过查看校园网用于登录的JavaScript代码: ![输入图片说明](.idea/image8.png) 可得到登录执行的接口方法: ![输入图片说明](.idea/image9.png) 从而得知页面输入的密码由do_encrypt_rc4()方法加密过,通过查看代码得知: ![输入图片说明](.idea/image10.png) 其采用的方法是使用了RC4算法,通过输入字符串与当前时间戳进行运算得出新字符串,在密码学中,RC4(来自Rivest Cipher 4的缩写)是一种流加密算法,密钥长度可变。它加解密使用相同的密钥,因此也属于对称加密算法。RC4是有线等效加密(WEP)中采用的加密算法,也曾经是TLS可采用的算法之一。 Ps:https://baike.baidu.com/item/RC4/3454548?fr=aladdin 那么data表单中的UNIX时间戳rc4key的作用就知道了,现在就要在python中实现rc4算法,把上边的JavaScript版本翻译成Python版本: ![输入图片说明](.idea/image11.png) 同时获取UNIX时间戳作为rc4Key: ![输入图片说明](.idea/image12.png) 现在设置好data就可以进行登陆 ![输入图片说明](.idea/image13.5.png) 由于http请求成功会返回200状态码 我们可以通过这个状态码来判断是否登陆成功: ![输入图片说明](.idea/image13.png) 但是依然存在的问题就是账号密码是写死的,不够灵活,但我们可以通过读取Json文件来解决问题: ![输入图片说明](.idea/image14.png) ![输入图片说明](.idea/image15.png) 逻辑为用户第一次登陆需要命令行窗口输入账号密码然后回车进行登陆,如果登录成功,会将账号密码以json格式保存在login_data.json里,且位置为D盘,保存位置可以通过os.chdir()方法更改,这个方法可以改变工作目录,达到更改目录的效果,这样下一次登陆,就会读取login_data.json里的数据进行登陆,无需二次输入。 现在我们将其使用**auto-py-to-exe** 这个包打包成exe文件: ![输入图片说明](.idea/image16.png) 使其脱离python运行环境,在任何一台电脑都可直接点击运行使用无需python环境。 现在来完成自动化配置,搭配windows系统自带的任务计划程序,我们可以设置自动任务,定时运行这个程序来达到自动登陆校园网的目的,一般用户我们可以设置为: ![输入图片说明](.idea/image17.png) 触发器设置为开机即启动或者连接上网络就启动。 但是由于服务器需要24小时保持网络连接,所以就需要特殊考虑汕职院校园网的两大特性:**一是每日00:00必定清除登陆认证,二是2小时内无流量流通就清除登陆认证**。那么就需要让程序在00:00的时候登陆且保证24小时内每两个小时内都有在上网,最简单的解决方法是设置每隔一个小时登陆一次,办法虽好,但存在的风险是频繁的可能会被检测为异常用户进行封号处理,所以需要对程序进行改进: ![输入图片说明](.idea/image19.png) 加入网络判断,使用ping命令去ping百度或者其他网站,ping即有在进行网络流通,且如果ping成功即为0,则关闭程序,如果不为0,即没有网络连接超时,进行登陆。这样一来程序就变成了自动选择性的登录,运行就检查网络,有网就关闭,无网就登陆。 只要设置成每隔一个小时登陆一次,就完美避开了校园网的两个特性。 完成了对校园网登录的智能登录。 **Ps****:运行效果** **第一次登录:** ![输入图片说明](.idea/image20.png) **二次登录的网络检测(无网):** ![输入图片说明](.idea/image21.png) **二次登录的网络检测(有网):** ![输入图片说明](.idea/image23.png) **生成存储账号密码的文件:** ![输入图片说明](.idea/image24.png) **运行流程:** ![输入图片说明](.idea/image26.png) 完整代码: ```python import json import os import time import requests os.chdir('D:') file_name = "login_data.json" url = 'http://1.1.1.3/ac_portal/login.php' # RC4加密算法 def rc4(src: str, passwd: str) -> str: i, j, a, b, c = 0, 0, 0, 0, 0 key, sbox = [], [] plen = len(passwd) size = len(src) output = "" for i in range(256): key.append(ord(passwd[i % plen])) sbox.append(i) for i in range(256): j = (j + sbox[i] + key[i]) % 256 temp = sbox[i] sbox[i] = sbox[j] sbox[j] = temp for i in range(size): a = (a + 1) % 256 b = (b + sbox[a]) % 256 temp = sbox[a] sbox[a] = sbox[b] sbox[b] = temp c = (sbox[a] + sbox[b]) % 256 temp = ord(src[i]) ^ sbox[c] temp = str(hex(temp))[-2:] temp = temp.replace('x', '0') output += temp return output if not os.path.exists(file_name): account = input("请输入你的账号: ") password = input("请输入你的密码: ") res = { 'account': account, 'password': password } print(res) with open(file_name, "w+") as fp: fp.write(json.dumps(res)) else: results = os.system('ping www.baidu.com') if results != 0: with open(file_name, "r") as fp: res = json.loads(fp.read()) account = res['account'] password = res['password'] rc4key = int(time.time() * 1000) pwd = rc4(password, str(rc4key)) data = { "opr": "pwdLogin", "userName": account, "pwd": pwd, "rc4Key": rc4key, "rememberPwd": "0" } header = { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,zh;q=0.9", "Connection": "keep-alive", "Content-Length": "88", "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", "Host": "1.1.1.3", "Origin": "http://1.1.1.3", "Referer": "http://1.1.1.3/ac_portal/default/pc.html?template=default&tabs=pwd&vlanid=0&url=http://www.msftconnecttest.com%2fredirect", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36", "X-Requested-With": "XMLHttpRequest" } result = requests.post(url, data, headers=header).status_code if result == 200: print("用户:" + account + ",登陆成功,状态码为:" + format(result)) else: print("用户:" + account + ",登陆失败,状态码为:" + format(result)) ```