写作缘由

学校校园网的登录认证的主要方式是连接有线或者无线,之后等系统弹出登录网页,或者你自己上一个网站,会自动跳转到登录界面,在大多数情况下,这没有什么问题,但是在人比较多的时候,比如图书馆,或者信号覆盖不是很好的时候,就不会弹出这个页面,网络状态直接显示感叹号,网页打不开,更有甚者,即便是手动输入认证服务器网址,也有一定几率打不开登录页面。

这个程序本来是写给自己用来自动登录有线网的,在NAS里做自动开机登录使用,这个脚本写的很简单,就十几行代码。后来想要自己的笔记本也可以自动登录无线网,就扩充了下脚本,但是,当真正开始用的时候,发现了很多的问题,这些问题都是脚本难以解决的,就干脆把脚本扩展成了GUI程序,并且同时支持了无线网络和有线网络的登录,以及旧认证服务器和新认证服务器的自动切换登录。

语言和依赖

Python 3.X,需要安装requests包(脚本)以及pyqt5包(GUI)。
测试平台为Windows 10 X64,macOS HS。

网络概况

这是2018年1月份写的程序,在这个时候,学校的校园网主要包含有线和无线两种连接方式,其中有线,包括校园网有线、三家运营商的有线,这四种登录方式使用的是新的服务器,也就是2017年底部署的新的认证服务器,登录网址为login.ccnu.edu.cn,或者l.ccnu.edu.cn,或者是10.220.250.50,认证地址为:

http://10.220.250.50/0.htm

无线的话,比较复杂,在不同地方的无线服务器不同,有些地方,比如图书馆,使用的是新的认证服务器(登陆界面包含输入用户名、密码、运营商选择三个部分),认证地址和上面的一样。但是,在大部分学校的其它地方,比如田家炳楼、宿舍无线使用的是旧的服务器,其打开界面后没有选择运营商的RadioButton,只有输入用户名和密码的地方,其认证地址为:

http://securelogin.arubanetworks.com/auth/index.html/uauth/index.html/u

但是,有些时候,在本该属于新服务器认证的地方,偶尔会跳转到旧服务器认证,所以,如果想要正确登录,就需要尝试不同的服务器,但是,新的问题是,在旧服务器认证的时候,新服务器地址是可以POST通的,并且可以正常返回200并打开正常登录页面的,但是,其它正常外网网页是登不上的,因此,设计自动登录程序的时候当POST返回200和正确网页之后还需要测试是否可以打开外网,更有甚者,很多时候,就算是正确的服务器,POST返回200和正确网页后还是打不开外网,这极大增加了登录脚本的复杂度。

代码

直接上程序吧,具体项目参见我的Github仓库。唯一感叹一点的就是,区区四五行的POST登陆,真正实现成一个功能,竟然写了个500行的程序,其中接近400行处理相关逻辑,100行左右处理UI。一个遗憾是,没有使用多线程,因为Qt的多线程还没有开始学习,Python的多线程和PyQt兼容性不太好,并且也不安全,所以就没有用。

这个是脚本,postit.py,可以直接使用,不过要实现自动登录、自动判断登录状态并且在多次登录失败的情况下切换新旧服务器,以及GUI的话,就需要另一个main.py文件。

postit.py

#!/usr/bn/env python3
import requests,json
import traceback
def loginCCNU(username="",passwd="",suffix=""):errmessage = Nonetry:url = "http://10.220.250.50/0.htm"payload = {"DDDDD":"%s"%username,"upass":"%s"%passwd,"suffix":"%s"%suffix,"0MKKey":"123"}headers = { "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36","Content-Type": "application/x-www-form-urlencoded",}r = requests.post(url, data=payload ,headers = headers)# print(r.text)if "您已登录成功,欢迎使用!请不要关闭本页。" in r.text:return str(r.status_code),"1",errmessageelse:return str(r.status_code),"0",errmessageexcept:errmessage = str(traceback.format_exc())return None,"0",errmessagedef loginoutCCNU(username="",passwd="",suffix=""):errmessage = Nonetry:url = "http://10.220.250.50/F.htm"headers = { "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36","Content-Type": "application/x-www-form-urlencoded",}r = requests.get(url ,headers = headers)# print(r.text)if "华中师范大学无线校园网登录" in r.text:return str(r.status_code),"0","已注销"else:return str(r.status_code),"0","返回未知网页"except:errmessage = str(traceback.format_exc())return None,"0",errmessagedef loginoutCCNUWLAN(username="",passwd="",suffix=""):errmessage = Nonetry: url = "http://securelogin.arubanetworks.com/cgi-bin/login?cmd=logout"headers = { "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36","Content-Type": "application/x-www-form-urlencoded",}r = requests.get(url ,headers = headers)# print(r.text)if "Logout Successful" in r.text:return str(r.status_code),"0","已注销"else:return str(r.status_code),"0","返回未知网页"except:errmessage = str(traceback.format_exc())return None,"0",errmessagedef loginCCNUWLAN(username="",passwd=""):errmessage = Nonetry:url = "http://securelogin.arubanetworks.com/auth/index.html/uauth/index.html/u"payload = {"user":"%s"%username,"password":"%s"%passwd}headers = { "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36","Content-Type": "application/x-www-form-urlencoded",}r = requests.post(url, data=payload ,headers = headers)# print(r.text)if "External Welcome Page" in r.text:return str(r.status_code),"1",errmessageelif """Internal Server Error""" in r.text:# return str(r.status_code),"1",errmessagereturn str(200),"1",errmessageelse:return str(r.status_code),"0",errmessageexcept:errmessage = str(traceback.format_exc())return None,"0",errmessage
# 502 0 电缆未连通
# 403 0 用户错误
# 200 0 账户错误
def testNet(number = 1):initnumber = numbererrmessage = Nonecode = 0headers = { "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"}if not str(number).isdigit() or number < 1:raise ValueError("设置的循环次数错误")try:while number >= 1:try:r = requests.get("http://www.blibili.com",timeout=0.8,headers=headers,verify=False)code = r.status_code# print(r.text)# print("refresh" in r.text)if r.status_code == 200:if not "Dr.COMWebLoginID_0.htm" in r.text and not """meta http-equiv='refresh' content='1;""" in r.text:breakelse:code = 0except:pass# print(str(traceback.format_exc()))number -= 1except:errmessage = str(traceback.format_exc())finally:if errmessage != None:return None,"0",errmessageelif code != 0:return str(code),"1","测试%s次,最终通过测试。"%(initnumber - number + 1)else:return None,"0","测试%s次,均未通过测试。"%initnumberdef superLogin(username="",passwd="",choose=""):username = str(str(username).split("@")[0])if choose == (True,False,False,False,False):suffix = "0"elif choose == (False,False,True,False,False):username += "@chinanet"suffix = "1"elif choose == (False,False,False,True,False):username += "@cmcc"suffix = "2"elif choose == (False,False,False,False,True):username += "@unicom"suffix = "3"else:return None,0,"POST的字段不合法,请重试。"# print(username,passwd,suffix)return loginCCNU(username,passwd,suffix)if __name__ == "__main__":# print(testNet(5))# print(loginCCNUWLAN("2017110",""))print(loginoutCCNUWLAN("2017110",""))# # a,b,c=superLogin("2017110","",(False,False,True,False))# # print(a,type(a))# print(loginoutCCNU("2017110","","2"))# print(testNet(5))

main.py

GUI界面主程序,需要UI布局文件/资源文件/postit.py模块才可使用,请前往Github仓库下载项目文件。
#!/usr/bin/env python3
# -*- coding:utf8 -*-
import sys,traceback,time
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import UI_main,RC_main
import postit
import time__title__ ="CCNU校园网自动登录器"
__version__ = "0.3.6"
__log__ = """0.0.1 \n完成了大致的UI设计,用户名和密码会根据设置自动保存。现在你可以使用静默登录功能, 在Windows开机的时候进行登录, 登录成功后程序会自动退出。
\n0.0.2 \n修改了默认的连接时间,静默模式下系统会在程序加载5s后开始POST请求,之后10s内如果返回200状态,并登录成功且不进行其它操作则自动退出。
\n0.0.3 \n程序在静默模式下如果没有得到200状态码,则会重复POST10次,最后返回结果。
\n0.1.0 \n添加了一个自己绘制的图标,灵感来源于“网”字,以及华大的Logo。静默登陆次数更改为15次。
\n0.1.2 \n静默登录时打开界面后可以在信息栏了解当前进行的每次重连信息了。
\n0.2.0(2018-01-21) \n程序优化和重构,使用了信号和QTextbrowser代替QLabel显示连接信息。
\n0.3.0(2018-01-25) \n程序第二次重构,增加了一堆功能,最后又全部删掉了,现在更简洁。具体来说,就是,增加了有线和无线两种连接,提供一个登录失败自动\
切换的选项,提供了几个可以供测试人员测试当前连接的按钮,这几个按钮写的很漂亮,登录后按钮会被选中,注销后则自动弹起。
\n0.3.3(2018-01-25) \n提供了帮助文档。优化了连接的逻辑,界面UI等。解决了自动从旧服务器跳转连接到新服务器中出现的错误,\
现在默认会自动选择“校园网账号”继续新服务器连接。同时我们对之前未成功的POST连接提供了注销的操作,以免出现其他问题。
\n0.3.4(2018-01-25) \n修复了连接过程自动切换连接服务器时对于是否连接上网判断的一个Bug。
\n0.3.5(2018-01-25) \n在新网/旧网×正确/错误连接×直接登录/静默登录这八种情况下进行了单元测试,解决了一些出现的问题,\
现在系统可以在连接失败的情况下自动切换网络进行重新测试,在静默条件下这两个服务器的测试都是多次进行的,在直接登录条件下只进行一次(由于POST后立即GET Baidu会有一些问题,\
因此在这种情况下,程序在打不开百度的情况下也会进行4次重试)。
\n0.3.6(2018-01-26) \n修复一些BUG,优化了部分性能,测试互联网连通性超时更改为0.8s,判断次数更改为3次,之前为1s、5次。由于有时候POST返回200和正常登录成功界面,但是依旧通不过连接测试,\
所以程序对每次POST都进行了连通性的检查,在点击“登录”按钮时甚至也进行了多次POST与检查,以避免将请求错误的转移到其它服务器,这可能造成一些UI显示上的卡死问题(尚未通过多线程解决此问题)。\
在goPost()进行检查的时候,添加了1s的延迟以备服务器端准备完毕。"""
__help__ = """<html><head/><body><p>本程序适用于华中师范大学无线网络(SSID名为"CCNU")以及有线网络(包括校园有线、移动、联通和电信),提供一个方便快捷的账号认证服务。</p>
<p><span style=" font-weight:600;">自动登录指南:</span></p>
<p>1、本程序设计的一个重要目的是为了计算机的开机自动登录。您必须确认勾选了“保存密码到注册表”、正确填写了您的用户名和密码并且选择了“不显示界面自动登录”选项。为保证登录的可靠性和方便性,建议您勾选“允许自动切换服务器进行登录”。之后请按下“Windows + R”组合按键,输入“shell:startup”,将程序移动到此文件夹中即可实现开机登录。</p>
<p>敬告:如果您不允许“自动切换服务器进行登录”,则您需要手动指定登录才可以正常联网。比如,当您使用笔记本在田家炳楼(旧服务器)登录时,您选择了“校园WLAN”选项,但是如果您在图书馆登录时(使用的是新服务器),如果不勾选“自动切换服务器”,将不会顺利登录。</p>
<p><span style=" font-weight:600;">调试指南:</span></p>
<p>1、点选“测试”按钮可以打开调试界面,在此你可以对不同服务器进行登录,对当前联网状态进行测试。当进行某个服务器的登录后,登录按钮将被选中,只有点击其右边的“注销”后选中状态才会解除。</p>
<p><span style=" font-weight:600;">安全须知:</span></p>
<p>1、使用“自动登录”需打开“保存密码到注册表”选项,您的密码只会保存在本地,不会被上传。您可以使用抓包工具对此承诺进行验证。</p>
<p>2、本程序使用的“测试登录”会向“https://www.baidu.com”发送包含文件头部的Get请求,其中不包含任何隐私和统计数据。您可以使用抓包工具对此承诺进行验证。</p>
<p><span style=" font-weight:600;">程序范围</span></p><p>本程序适用于Windows NT内核,XP以上64位操作系统,包括Windows XP、Windows Vista、Windows 7、8、8.1、10。</p></body></html>"""class Main(QDialog,UI_main.Ui_Dialog):postit_callback = pyqtSignal(str)def __init__(self,parent =None):super(Main,self).__init__(parent)self.setupUi(self)self.notshow = Trueself.index = 1settings = QSettings()self.userrole = settings.value("UserRole")setting_geo = settings.value("MainWindow/Geometry")if setting_geo is not None:self.restoreGeometry(setting_geo)# 默认配置和用户配置载入self.checkBox_keeppasswd.setChecked(True)self.checkBox_keeppasswd.setToolTip("""选择此项后将会自动保存密码到注册表。\n如果您要启用“不显示界面直接登陆”功能,请确保此项打开。""")self.checkBox_auth.setToolTip("选择此项后,你可以将程序添加到开机任务中,系统会自动尝试多次登录")self.checkBox_server.setToolTip("选择此项后,当使用指定服务器无法登录时系统会切换到其他服务器进行尝试\n当从旧服务器切换到新服务器时,会默认使用校园网账号进行连接。")self.radioButton_school.setToolTip("图书馆CCNU WLAN和有线(包含三家运营商和校园有线)采用的是新服务器")self.radioButton_wlan.setToolTip("除了图书馆的其余地方的CCNU WLAN采用的是旧服务器")self.pushButton_test.hide()self.pushButton_lanlogin.hide()self.pushButton_lanlogout.hide()self.pushButton_wlanlogin.hide()self.pushButton_wlanlogout.hide()QTimer.singleShot(0,self.loadInitialSettings)# 信号处理,系统脚标self.pushButton_test.clicked.connect(self.testLogin)self.pushButton_lanlogin.clicked.connect(self.testLogin)self.pushButton_lanlogout.clicked.connect(self.testLogin)self.pushButton_wlanlogin.clicked.connect(self.testLogin)self.pushButton_wlanlogout.clicked.connect(self.testLogin)self.pushButton_login.clicked.connect(self.goLogin)# self.pushButton_login.setToolTip("进行登录\n按下此按钮只会登录一次")self.pushButton_about.clicked.connect(self.aboutMe)self.pushButton_about.setToolTip("关于此程序和其作者")self.postit_callback.connect(self.updateInfo)self.createTrayIcon()self.trayIcon.messageClicked.connect(self.traymessageClicked)self.pushButton_exit.clicked.connect(self.fullClose)# self.pushButton_exit.setToolTip("退出程序而不是变成一个托盘隐藏到后台")self.pushButton_help.clicked.connect(self.showHelp)self.pushButton_help.setToolTip("帮助")self.pushButton_more.clicked.connect(self.showMore)self.pushButton_more.setToolTip("网络连接测试")# 细节UIself.setWindowFlags(Qt.WindowCloseButtonHint)self.setWindowTitle("%s v%s"%(__title__,__version__))def showMore(self):if isinstance(self.sender(),QPushButton):if self.pushButton_more.text() == "简要(&S)":self.pushButton_more.setText("测试(&T)")self.pushButton_test.hide()self.pushButton_lanlogin.hide()self.pushButton_lanlogout.hide()self.pushButton_wlanlogin.hide()self.pushButton_wlanlogout.hide()else:self.pushButton_more.setText("简要(&S)")self.pushButton_test.show()self.pushButton_lanlogin.show()self.pushButton_lanlogout.show()self.pushButton_wlanlogin.show()self.pushButton_wlanlogout.show()def updateInfo(self,info = ""):# print(self.sender()) <__main__.Main object at 0x00000160EF4BCC18>old = self.textBrowser_info.toHtml()if len(old) > 2000:old = ""new = old + "<p>" + infonew = new.replace("[第1次连接]","[尝试连接]")# tail = new.split("\n")[-1]self.textBrowser_info.setHtml(new)self.textBrowser_info.moveCursor(QTextCursor.End)def loadInitialSettings(self):try:self.restoreUserrole()self.trayIcon.show()self.postit_callback.emit("读取设置成功")if self.userrole[4] == True:self.notshow = TrueQTimer.singleShot(2000,self.goSlience)return 0self.show()return 0except:# QMessageBox.warning(self,"warn",str(traceback.format_exc()))self.postit_callback.emit("欢迎使用")self.show()def loadUserrole(self):user = self.lineEdit_user.text()passwd = self.lineEdit_passwd.text()choose = (self.radioButton_school.isChecked(),self.radioButton_wlan.isChecked(),self.radioButton_ct.isChecked(),self.radioButton_cmcc.isChecked(),self.radioButton_cu.isChecked())keeppasswd = self.checkBox_keeppasswd.isChecked()slience = self.checkBox_auth.isChecked()autologin = self.checkBox_server.isChecked()self.userrole = [user,passwd,choose,keeppasswd,slience,autologin]def restoreUserrole(self):self.lineEdit_user.setText(self.userrole[0])self.lineEdit_passwd.setText(self.userrole[1])choose = self.userrole[2]self.radioButton_school.setChecked(choose[0])self.radioButton_wlan.setChecked(choose[1])self.radioButton_ct.setChecked(choose[2])self.radioButton_cmcc.setChecked(choose[3])self.radioButton_cu.setChecked(choose[4])self.checkBox_keeppasswd.setChecked(self.userrole[3])self.checkBox_auth.setChecked(self.userrole[4])self.checkBox_server.setChecked(self.userrole[5])def testLogin(self):if self.sender() == self.pushButton_lanlogin:self.pushButton_lanlogin.setChecked(True)self.goPost(choose = "lan",check_link_userrole=False)elif self.sender() == self.pushButton_lanlogout:self.pushButton_lanlogin.setChecked(False)code,_,_ = postit.loginoutCCNU()if code == "200":self.postit_callback.emit("[200] 成功注销您的新服务器登录。")elif self.sender() == self.pushButton_wlanlogin:self.pushButton_wlanlogin.setChecked(True)self.goPost(choose = "wlan",check_link_userrole=False)elif self.sender() == self.pushButton_wlanlogout:self.pushButton_wlanlogin.setChecked(False)code,_,info = postit.loginoutCCNUWLAN()if code == "200":self.postit_callback.emit("[200] 成功注销您的旧服务器登录。")elif self.sender() == self.pushButton_test:self.checkLink(show = 1)def goLogin(self):if self.checkLink(show = 0) == 1:self.postit_callback.emit("已连接互联网,已取消登录请求(可在“测试”选项注销服务器登录后再试)")else:r,code,_,check = self.goPost(choose = "",check_link_userrole=False)# 有可能存在没有连上网但是正确登录到服务器的情况。if code == "0" and r == "200":r,code,_,check = self.goPost(choose = "",check_link_userrole=True)if str(check) != "1":r,code,_,check = self.goPost(choose = "",check_link_userrole=True)if str(check) != "1":r,code,_,check = self.goPost(choose = "",check_link_userrole=True)if str(check) != "1":r,code,_,check = self.goPost(choose = "",check_link_userrole=True)if str(check) != "1":self.loadUserrole()autoserver = self.userrole[5]iswlan = self.userrole[2][1]userrole_temp = self.userroleif iswlan:try:postit.loginoutCCNUWLAN()except Exception as err:print("在旧服务器登出过程中发生错误")else:try:postit.loginoutCCNU()except Exception as err:print("在新服务器登出过程中发生错误")if autoserver:if iswlan:self.radioButton_school.setChecked(True)self.postit_callback.emit("旧服务器无响应,正尝试其他服务器")r,code,_,check= self.goPost(choose = "lan",check_link_userrole=True)if str(check) != "1":self.userrole = userrole_tempself.restoreUserrole()self.postit_callback.emit("""[FINAL]<span style=" color:#ff0000;"> 无法连接互联网。</span>""") elif not iswlan:self.postit_callback.emit("新服务器无响应,正尝试其他服务器")r,code,_,check = self.goPost(choose = "wlan",check_link_userrole=True)if str(check) != "1":self.postit_callback.emit("""[FINAL]<span style=" color:#ff0000;"> 无法连接互联网。</span>""")          else:self.postit_callback.emit("""[FINAL]<span style=" color:#ff0000;"> 无法连接互联网。</span>""")def goSlience(self):if self.checkLink(show=0) == 1:self.postit_callback.emit("已连接互联网,已取消登录请求(可在“测试”选项注销服务器登录后再试)")msgIcon_info = QSystemTrayIcon.MessageIcon(QSystemTrayIcon.Information)self.trayIcon.showMessage("已连接互联网","您已在线,已取消登录请求。",msgIcon_info)QTimer.singleShot(10000,self.autoClose)else:r,code,_,check = self.loginSlience(choose = "")# 有可能存在没有连上网但是正确登录到服务器的情况。# code = self.checkLink(show=0)# print("OUTCODE",code)if str(check) != "1":self.loadUserrole()autoserver = self.userrole[5]iswlan = self.userrole[2][1]userrole_temp = self.userroleif iswlan:try:postit.loginoutCCNUWLAN()except Exception as err:print("在旧服务器登出过程中发生错误")else:try:postit.loginoutCCNU() except Exception as err:print("在新服务器登出过程中发生错误")if autoserver:if iswlan:self.radioButton_school.setChecked(True)self.postit_callback.emit("旧服务器无响应,正尝试其他服务器")r,code,_,check = self.loginSlience(choose = "lan")# 如果尝试更换服务器依然失败,那么换回更换之前的设置。if str(check) != "1":self.userrole = userrole_tempself.restoreUserrole()elif not iswlan:# 因为使用wlan方式登陆不需要额外参数,因此只需要进行POST即可print("here")self.postit_callback.emit("新服务器无响应,正尝试其他服务器")r,code,_,check = self.loginSlience(choose = "wlan")else:self.postit_callback.emit("""[FINAL]<span style=" color:#ff0000;"> 无法连接互联网。</span>""")# QApplication.processEvents()def goPost(self,choose = "",check_link_userrole=True,show_check=True):# self.postit_callback.emit("登录中...")# 应该先判断是否当前有互联网连接,如果没有再继续下去。# 优先使用choose,如果没有choose字段,则使用userrole设置info = ""self.tryinfo = "[第%s次连接]"%self.indexothererr = Falsechecklink = Falseself.loadUserrole()user,passwd,choose_list = self.userrole[0],self.userrole[1],self.userrole[2]if choose == "wlan":print("旧服务器登录中...(来自于指定的登录方式)")response,code,errmesage = postit.loginCCNUWLAN(user,passwd)elif choose == "lan":print("新服务器登录中...(来自于指定的登录方式)")response,code,errmesage = postit.superLogin(user,passwd,choose_list)elif choose_list[1] == True:print("旧服务器登录中...(来自于用户自定义的登录方式)")response,code,errmesage = postit.loginCCNUWLAN(user,passwd)elif choose_list[1] != True:print("新服务器登录中...(来自于用户自定义的登录方式)")response,code,errmesage = postit.superLogin(user,passwd,choose_list)# print(response,code,errmesage)if response == "200":info += """<span style=" color:#00aa00;"> [200]网站已响应,</span>"""if code == "0":info = """<span style=" color:#ff0000;"> [200]网站已响应,但服务器返回了一个错误。</span>"""elif code == "1":info += """<span style=" color:#00aa00;">登录成功</span>"""self.index = 1self.tryinfo = "[连接成功]"checklink = check_link_userroleelif response == "403":info += """<span style=" color:#ff0000;"> [403]数据提交不完整,请重试</span>"""elif response == "502":info += """<span style=" color:#ff0000;"> [502]物理网络设备未正确设置</span>"""else:info += """<span style=" color:#ff0000;"> [ERR]其它错误。</span>"""othererr = Trueif othererr:# errmsg = QErrorMessage(self)# QErrorMessage.showMessage(errmsg,errmesage)print(errmesage)self.postit_callback.emit(self.tryinfo + info)if checklink and show_check:time.sleep(1)check = self.checkLink(show=1)elif checklink and not show_check:time.sleep(1)check = self.checkLink(show=0)elif not checklink:check = 2return response,code,errmesage,checkdef loginSlience(self,choose = "",loop = 5):index = 1response = code = errmessage = check =  NonemsgIcon_info = QSystemTrayIcon.MessageIcon(QSystemTrayIcon.Information)msgIcon_warn = QSystemTrayIcon.MessageIcon(QSystemTrayIcon.Warning)msgIcon_err = QSystemTrayIcon.MessageIcon(QSystemTrayIcon.Critical) while index < loop:# 根据UserRole进行自动选择,所以说这里的choose为空response,code,errmessage,check = self.goPost(choose = choose,check_link_userrole=True,show_check=False)print("LOGINSLIENCE",response,code,check)print("第%s次尝试登录"%index)index = index + 1if response == "200" and code == "1" and str(check) == "1":breakif response == "200" and code == "1":self.trayIcon.showMessage("登录成功","状态码[200],登录成功",msgIcon_info)QTimer.singleShot(10000,self.autoClose)elif response == "200" and code == "0":self.trayIcon.showMessage("登录失败","[200]网站已响应,但服务器返回了一个错误。",msgIcon_err)elif response == "403":self.trayIcon.showMessage("登录失败","[403]数据提交不完整,请重新输入。",msgIcon_err)elif response == "502":self.trayIcon.showMessage("登录失败","[502]网络未联通,请检查硬件连接。",msgIcon_warn)else:self.trayIcon.showMessage("登录失败","[ERR]硬件故障",msgIcon_err)return response,code,errmessage,checkdef checkLink(self,show=1):state,code,info = postit.testNet(3)if state == "200" and code == "1":if show != 0:self.postit_callback.emit("[测试连接] " + info)return 1elif state == None and code == "0":if show != 0:self.postit_callback.emit("[测试连接] " + info)return 0else:QMessageBox.information(self,"Website Checker",str(info)) def autoClose(self):if not self.isVisible():QTimer.singleShot(1000,self.fullClose)def fullClose(self):self.trayIcon.hide()self.close()app.quit()def hideEvent(self, event):msgIcon = QSystemTrayIcon.MessageIcon(QSystemTrayIcon.Information)self.trayIcon.showMessage("提醒","程序已隐藏,你可以通过此重新打开程序",msgIcon)def closeEvent(self, event):# close not quit also triggered this Eventself.loadUserrole()if not self.userrole[3]:self.userrole[1] = ""settings = QSettings()settings.setValue("UserRole",self.userrole)settings.setValue("MainWindow/Geometry",QVariant(self.saveGeometry()))def createTrayIcon(self):self.trayMenu = QMenu()showAction = self.trayMenu.addAction("打开主程序(&O)")showAction.triggered.connect(self.show)about = self.trayMenu.addAction("关于此程序(&A)")about.triggered.connect(self.aboutMe)self.trayMenu.addSeparator()quit = self.trayMenu.addAction("退出(&Q)")quit.triggered.connect(self.fullClose)self.trayIcon = QSystemTrayIcon(self)self.trayIcon.setIcon(QIcon(":/Main/Media/logo.png"))self.trayIcon.setContextMenu(self.trayMenu)self.trayIcon.activated.connect(self.iconActived)def traymessageClicked(self):self.show()def iconActived(self,reason):mouse = QCursor()if reason == QSystemTrayIcon.Trigger:self.show()elif reason == QSystemTrayIcon.Context:self.trayMenu.exec_(mouse.pos())def aboutMe(self):# QMessageBox.aboutQt(self,"About Qt")aboutDlg = QMessageBox()aboutDlg.about(self,"%s - About"%__title__,"""<html><head/><body><p>%s version %s    </p><p/><p>Written by <span style=" font-weight:600;">Corkine Ma</span></p><p>Email:cm@marvinstudio.cn    </p><p/><p>本程序使用 Python 和 Qt 开发,程序遵循GPL v2开源协议,你可以在<a href="http://tools.mazhangjing.com"><span style=" text-decoration: underline; color:#0000ff;">http://tools.mazhangjing.com</span></a> 此网站找到程序的源代码,如果没有,请联系作者。</p></body></html>"""%(__title__,__version__))# QMessageBox.information(self,"%s - 更新日志"%__title__,"%s"%__log__)box = AboutBox("%s"%__log__,"%s - 更新日志"%__title__,self)box.show()def showHelp(self):box = AboutBox("%s"%__help__,"%s - 帮助"%__title__,self)box.show()class AboutBox(QDialog):def __init__(self, text = "" ,title = "", parent =None):super(AboutBox,self).__init__(parent)self.info = QTextBrowser()self.info.setText(text)self.okbutton = QPushButton("确定(&O)")self.okbutton.clicked.connect(self.close)self.aboutbutton = QPushButton("官方网站(&W)")self.aboutbutton.clicked.connect(self.showWebsite)self.aboutqt = QPushButton("About &Qt")self.aboutqt.clicked.connect(self.aboutQt)layout = QVBoxLayout()layout.addWidget(self.info)blayout = QHBoxLayout()blayout.addWidget(self.aboutqt)blayout.addStretch()blayout.addWidget(self.aboutbutton)blayout.addWidget(self.okbutton)layout.addLayout(blayout)self.setLayout(layout)self.resize(QSize(500,400))self.setWindowTitle(title)def showWebsite(self):QDesktopServices.openUrl(QUrl("http://www.marvinstudio.cn"))def aboutQt(self):QMessageBox.aboutQt(self,"About Qt")
if __name__ == "__main__":app = QApplication(sys.argv)app.setApplicationName("CCNU Internet AutoLogin")app.setWindowIcon(QIcon(":/Main/Media/logo.png"))app.setApplicationVersion(__version__)app.setOrganizationName("Marvin Studio")app.setOrganizationDomain("http://www.marvinstudio.cn")app.setQuitOnLastWindowClosed(False)form = Main()if form.notshow == False:form.show()# box = AboutBox("fefe","fewf")# box.show()app.exec_()

Github仓库

博客地址:http://pybook.mazhangjing.com/Project_CCNULogin/
仓库地址:https://github.com/corkine/pyBook/tree/master/Project_CCNULogin
适用于64位PC的软件下载地址:https://github.com/corkine/pyBook/raw/master/Project_CCNULogin/dist/CCNULogin.rar

功能

1、静默登陆:程序添加到开机启动项并且勾选“静默登录”后,开机时会自动登录,程序不会显示主界面,只有状态栏图标和气泡通知。

2、记住密码:密码会保存在注册表,只保存在本地,不会上传。
3、自动切换服务器登录:当新服务器无法使用时,勾选此项会自动切换服务器重试。推荐搭配静默登录一起使用。
4、调试网络:在“调试”按钮下,你可以测试用户名、密码到各个服务器的连通性,当登录时,按钮会被选中,当你注销后会自动取消选中。
5、附加:当你当前已经连接网络时,程序不会继续登录,你可以在“调试”注销相应服务器后再登录。

Logo设计

这个程序的Logo是一个“网”字,底色采用了华大的标志色——青,构思还可以,起码比我之前自己随手从网上找的一个地球强一些,虽然这个也是在Ai里自己画的。我始终相信这一点:

> 一个花费心思制作的,并且每天都用到的东西,值得设计者让它好看一点,尽管好不好看并不是它的主要功能。

华中师范大学CCNU校园网(有线/无线)自动登录程序相关推荐

  1. 校园网网页认证自动登录

    校园网网页认证自动登录 python+定时任务 实现校园网自动登录 一.总览 二.具体步骤 python+定时任务 实现校园网自动登录 说明:因为我们学校校园网登陆需要网页认证,且每天3点左右会自动断 ...

  2. 补一补上周的坑,关于校园网设置路由器自动登录

    补一补上周的坑,关于校园网设置路由器自动登录的. 首先,先得明白校园网登录认证的过程发生了什么,表面需要的是用户名和密码,但是其实不止这些,在浏览器(我用的是chrome)地址栏里输入校园网认证地址1 ...

  3. python自动登录校园网_免费自动登录国科大校园网python脚本

    UCAS-Network-Login A python program that helps you log in UCAS network for free. 免费自动登录国科大校园网 声明:本软件 ...

  4. QQ批量自动登录程序的设计

    因为自己的QQ号码有好几个,每次重启机子的时候一个一个的登录超级麻烦,而且腾讯老是在偶尔的时候,再把以前已经记住密码的QQ密码给置空,还要重新输入,太麻烦,因此尝试着自己搞一个批量自动登录的程序 以T ...

  5. python mechanize自动登录程序

    放假回来了,很久没更新博客了,以后得常更新,今天给大家分享下python第3方的模块包:mechanize. mechanize是非常合适的模拟浏览器的模块,它的特点主要有: 1 http,https ...

  6. 校园网、CMCC自动登录

    最近学习简单的爬虫接触到selenium这个库 ,发现能自动操作浏览器,就想到写个简单的脚本自动连接校园网,试后发现屡试不爽,从此再也没见过登录认证界面

  7. php.c drcom,校园网绕过Drcom安装自动登录程序到路由器

    简单记录一下,怎么在路由器上安装drcom脚本,实现自动登陆,一个路由器,全寝室都可以使用的方法. 安装固件: 我这里使用的是newifi mini型号的路由器 下载后,插拔一次路由器,按下路由器上的 ...

  8. Python案例之QQ空间自动登录程序实现

    原网址:https://www.cnblogs.com/zlslch/p/7986680.html 前提就是你的电脑上安装了 python, selenium 使用chrome 浏览器,需要下载合适的 ...

  9. Python校园网定时自动登录-锐捷

    开始 搭了个树莓派连着校园网,但是校园网每天24点掉线,次日6点后才能连接,所以用Python写了个脚本,每天早上6点20执行一次,这样就不用每天手动登录了. 在写代码之前我们要先获取一些参数,而用这 ...

最新文章

  1. *** Procedure 存储过程 ***
  2. java:volatile,instanceof,strictfp关键字
  3. python 彩票 遗漏值_荐Python遗漏知识点一
  4. kubernetes常用对象
  5. 基于arm下的Linux控制,基于ARMuCLinux的网络控制系统设计与实现
  6. spring-data-mongodb查询结果返回指定字段
  7. mysql三高讲解(二):2.4 InnoDB数据表是如何存储的
  8. zjoi2018day1 游记
  9. 05【应用工具简介】PM 流程图,思维导图,原型图绘制?怎么绘制不被解雇?
  10. 数据仓库和数据挖掘基础知识点
  11. layui 勾选不联动父项 树形控件_layui树形组件重现勾选过程的办法
  12. 【Mixamo】记录mixamo导出动画踩的坑
  13. Java SE java基础 求营业额
  14. Android——USB转COM口(CH340)与传感器进行通讯
  15. 数电学习(十一、D/A和A/D转换)
  16. 下载文件时设置文件名的方法
  17. 自签名证书和CA机构颁发的证书的区别
  18. Java序列化与JNDI注入
  19. 五分钟学算法:前缀和系列
  20. 【语音变速】变速不变调+变速变调

热门文章

  1. 叙事、画面和音效:解析VR游戏设计要点
  2. 7628刷breed_自制各类路由原厂直刷Breed的文件,无需修改mac无需重刷无线
  3. 说说 Redis pipeline
  4. 向mysql表中插入/更新数据时自动添加创建时间/更新时间
  5. 告诫程序员们,大三/大四有必要去实习吗?
  6. 服务器所属文件变成nobody,NFS使用autofs挂接后文件属主显示为nobody
  7. Python实现QQ模拟登录
  8. 前端进击的巨人(六):知否知否,须知this
  9. T1.特殊的毕达哥拉斯三元数(11.19)
  10. 用BQ30Z55替换BQ40Z50