日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

python实现oa系统_技术讨论 | 利用Python程序实现某OA系统的自动定位

發(fā)布時(shí)間:2023/12/19 python 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python实现oa系统_技术讨论 | 利用Python程序实现某OA系统的自动定位 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

本文介紹了筆者通過(guò)python程序?qū)崿F(xiàn)某OA系統(tǒng)自動(dòng)考勤打卡功能及相關(guān)邏輯原理的解析。

聲明:本程序僅供Python語(yǔ)言的學(xué)習(xí)交流用途,筆者不提倡利用程序自動(dòng)考勤的做法,筆者不對(duì)濫用本程序?qū)е碌娜魏魏蠊?fù)責(zé)。

需求分析

疫情期間,筆者所在公司使用某OA系統(tǒng)的考勤功能代替原來(lái)的刷臉考勤,結(jié)果導(dǎo)致很多人經(jīng)常忘記打卡,于是筆者尋思著能不能寫(xiě)個(gè)程序?qū)崿F(xiàn)自動(dòng)考勤,希望實(shí)現(xiàn)的主要功能是:指定用戶名密碼登錄和指定時(shí)間簽到簽退,擴(kuò)展功能是:自定義簽到和簽退的IP或定位地址。

系統(tǒng)邏輯分析

為了通過(guò)python實(shí)現(xiàn)上述功能,首先需要人工訪問(wèn)系統(tǒng)進(jìn)行相關(guān)的操作,并抓包分析請(qǐng)求和返回?cái)?shù)據(jù),弄清邏輯原理,下面介紹分析過(guò)程:

登錄

訪問(wèn)OA系統(tǒng)登錄頁(yè)面,點(diǎn)擊輸入登錄信息后截取登錄數(shù)據(jù)包,分析發(fā)現(xiàn)登錄接口除了驗(yàn)證用戶名和密碼外,還會(huì)驗(yàn)證下圖紅框所示的cookie和token參數(shù)。因此我們需要找到這兩個(gè)參數(shù)值從哪里獲取。

重新訪問(wèn)登錄頁(yè)面并抓取返回包,首先從返回包頭部看到了JSESSIONID參數(shù),而另一個(gè)lt參數(shù)則在返回頁(yè)面的源碼中。

弄清楚這兩個(gè)參數(shù)的來(lái)源后,我們重新回到登錄頁(yè)面提交登錄請(qǐng)求,獲取并記錄下會(huì)話cookie。

考勤

登錄賬號(hào)后,進(jìn)入考勤模塊進(jìn)行打工并截取數(shù)據(jù)包,可以看出程序是通過(guò)向考勤接口提交參數(shù)值為CHECKIN和CHECKOUT的json字符串以實(shí)現(xiàn)簽到和簽退。

另外可以看到請(qǐng)求包中攜帶了好幾個(gè)cookie參數(shù),經(jīng)過(guò)不斷的測(cè)試排除后,最終確定WEBID、JSESSIONID和ETEAMSID這三個(gè)為關(guān)鍵cookie,其余幾個(gè)都可以忽略。

自定義考勤地址

上述測(cè)試過(guò)程是PC端的,由于其中并沒(méi)有涉及到地址的參數(shù),因此轉(zhuǎn)到APP端進(jìn)行測(cè)試。截取APP端的考勤請(qǐng)求包,可以看到checkaddress參數(shù)就是考勤定位地址。

筆者嘗試在PC端的考勤請(qǐng)求參數(shù)中插入checkaddress,從響應(yīng)包中可以看出已經(jīng)成功使用該參數(shù)自定義考勤地址進(jìn)行考勤,同時(shí)這里如果再加入經(jīng)緯度參數(shù)的話,即可高度模擬定位考勤。

值得關(guān)注的是,筆者分析發(fā)現(xiàn)當(dāng)考勤請(qǐng)求攜帶了PC端UA時(shí),服務(wù)端會(huì)將客戶端識(shí)別為PC端,此時(shí)不會(huì)處理checkaddress參數(shù),簽到地址就是客戶端的真實(shí)IP地址。當(dāng)考勤請(qǐng)求攜帶移動(dòng)端UA或者pythonUA時(shí),服務(wù)端會(huì)將客戶端識(shí)別為移動(dòng)端且處理checkaddress參數(shù),此時(shí)就可以實(shí)現(xiàn)自定義考勤地址,包括IP地址和地理位置。

邏輯梳理

通過(guò)上述操作后,筆者已經(jīng)了解到登錄接口和考勤接口的邏輯和請(qǐng)求形式,下面簡(jiǎn)單梳理相關(guān)流程,這個(gè)流程也就是后續(xù)編寫(xiě)程序主要的邏輯依據(jù):1.【用戶訪問(wèn)登錄頁(yè)面】

||

\/

2.【登錄頁(yè)面返回一個(gè)cookie(JSESSIONID)和token(lt)】

||

\/

3.【用戶攜帶cookie像登錄接口提交token、用戶名和密碼】

||

\/

4.【登錄接口驗(yàn)證成功后返回會(huì)話cookie(ETEAMSID\JSESSIONID\)】

||

\/

5.【用戶攜帶會(huì)話cookie向考勤接口提交簽到/簽退請(qǐng)求】

功能實(shí)現(xiàn)

這里先回顧一下本程序?qū)崿F(xiàn)需求是:指定用戶名密碼登錄和指定時(shí)間簽到簽退。通過(guò)上述邏輯梳理,已經(jīng)可以實(shí)現(xiàn)指定用戶和密碼登錄已經(jīng)簽到簽退,另外還需要實(shí)現(xiàn)的就是指定時(shí)間,下面我們加入指定時(shí)間相關(guān)的功能再次梳理python程序的主要功能邏輯:1.【輸入用戶名、密碼、簽到簽退時(shí)間運(yùn)行程序】

||

\/

2.【登錄系統(tǒng)獲取會(huì)話cookie】

||

\/

3.【程序獲取本地時(shí)間】

||

\/

4.【程序比對(duì)本地時(shí)間和用戶設(shè)定時(shí)間】

||

\/

5.【在指定時(shí)間攜帶會(huì)話cookie進(jìn)行考勤】

程序結(jié)構(gòu)

梳理出程序主要功能邏輯后,開(kāi)始定義函數(shù)分別實(shí)現(xiàn)上述主要功能,下面列出程序的主要函數(shù)結(jié)構(gòu):def get_cookie(user,passwd):登錄系統(tǒng),獲取會(huì)話cookie,該函數(shù)實(shí)現(xiàn)了[邏輯梳理]中的第2-4步

def keep_session():維持會(huì)話cookie有效性,因cookie長(zhǎng)期不活躍會(huì)失效,因此通過(guò)此函數(shù)訪問(wèn)系統(tǒng)以維持cookie,如果cookie已經(jīng)失效,則會(huì)調(diào)用get_cookie函數(shù)重新登錄獲取cookie

def check_in():簽到模塊,攜帶cookie向考勤接口提交CHECKIN

def check_out():簽退模塊,攜帶cookie向考勤接口提交CHECKOUT

def get_position():定位模塊,根據(jù)用戶輸入的地理位置獲取經(jīng)緯度

def check_time():獲取本地時(shí)間并于用戶設(shè)定時(shí)間作比對(duì),觸發(fā)考勤模塊和會(huì)話維持模塊

def main():程序入口函數(shù),獲取用戶輸入

代碼解析

通過(guò)上面的介紹,我們已經(jīng)大概了解整個(gè)程序的運(yùn)行邏輯,下面對(duì)部分關(guān)鍵代碼進(jìn)行解析(部分常規(guī)代碼有省略):def get_cookie(user,passwd):

...........

token = re.search(r'LT\S+cn',html).group()

#urllib訪問(wèn)登錄頁(yè)面后,從頁(yè)面中獲取lt參數(shù)值,即token

pcookie = re.search(r'JSESSIONID=\S+',str(pres.info().headers)).group()

#訪問(wèn)登錄頁(yè)面后,從返回包頭部中獲取cookie,后續(xù)提交登錄請(qǐng)求時(shí)需要攜帶該cookie

data ='lt='+token+'&execution=e1.2&j_pcClient=&_eventId=submit&isApplyed=false&ampregisterSourceUrl=&ampregisterSource=&ampregisterDataSource=&username='+user+'&password='+passwd

#組合token和用戶輸入的登錄信息,用于組成登錄請(qǐng)求

req = urllib2.Request(lurl)

cj = cookielib.CookieJar()

opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))

#通過(guò)cookiejar記錄登錄成功后頁(yè)面返回的會(huì)話cookie

opener.addheaders = [('Cookie',pcookie)]

#在登錄請(qǐng)求包頭中加入一開(kāi)始獲取到的cookie

try:

res = opener.open(lurl,data=data,timeout=10)

except urllib2.URLError:

print '[ERROR]Urlllib error, retry later'

try:

cookie = re.search(r'ETEAMSID=\w+',str(cj)).group()+';'+re.search(r'JSESSIONID=\w+',str(cj)).group()+';'+re.search(r'WEBID=\w+',str(cj)).group()

#到這一步已經(jīng)登錄成功,cookiejar已經(jīng)記錄了會(huì)話cookie,記錄形式是這樣的:

, , ]>

因此這里利用正則匹配出我們所需要的3個(gè)cookie值

print '[INFO]Login succeed, your cookie is:'+cookie

...........def check_in():

............

req = urllib2.Request(curl)

req.add_header("Cookie",cookie)

req.add_header("Content-Type","application/json")

if stat == '0':

data = json.dumps({"type":"CHECKOUT","checkAddress":addr,"longitude":longi,'latitude':lati})

#當(dāng)用戶自定義了考勤地址時(shí),且成功獲取到經(jīng)緯度信息時(shí),提交的請(qǐng)求中加入了地理位置和經(jīng)緯度參數(shù),服務(wù)端默認(rèn)將urllib的UA識(shí)別為移動(dòng)端,故會(huì)記錄用戶提交的地理信息,完美模擬定位考勤效果

elif stat == '1':

data = json.dumps({"type":"CHECKOUT","checkAddress":addr})

#當(dāng)用戶自定義了考勤地址時(shí),但未成功獲取到經(jīng)緯度信息時(shí),提交的請(qǐng)求中只加入地理位

elif stat =='2':

req.add_header('User-Agent',ua)

data = json.dumps({"type":"CHECKOUT"})

#當(dāng)用戶未自定義考勤地址時(shí),提交的請(qǐng)求按PC端原始格式,且此處需要加入自定義的PC端UA,否則服務(wù)端會(huì)將簽到地址記錄為空值

try:

res = urllib2.urlopen(req,data=data,timeout=5).read()

smsg = res.find('簽到成功')

fmsg = res.find('簽到失敗')

if smsg > -1:

print '[INFO]'+time.strftime('%Y-%m-%d_%H:%M',time.localtime())+' Checkin succeed'

elif fmsg > -1:

print '[WARNING]'+time.strftime('%Y-%m-%d_%H:%M',time.localtime())+' Checkin fail:'+res

#以上代碼通過(guò)在返回報(bào)文中查找成功和失敗的字符,作為考勤是否成功的判斷依據(jù),并輸出到終端提示用戶

..........def check_time():

while True:

ltime = time.strftime('%H:%M',time.localtime()).lstrip('0')

day = time.strftime('%a',time.localtime())

#獲取當(dāng)前的時(shí)間,lstrip去0是為了時(shí)針為0-9的個(gè)位數(shù)時(shí)進(jìn)行格式統(tǒng)一

..........

if ltime == '4:30':

keep_session()

time.sleep(60)

#由于會(huì)話cookie在一定時(shí)間后(貌似是十幾個(gè)小時(shí))會(huì)失效,因此設(shè)定在凌晨調(diào)用keepsession()維持cookie

elif ltime == intime.lstrip('0') and day not in ('Sat','Sun'):

#比對(duì)本地時(shí)間與用戶輸入時(shí)間,且判斷是否周末

keep_session()

#進(jìn)行考勤前,再次檢驗(yàn)cookie是否有效

rnd = random.randint(0,600)

print '[INFO]Checkin after ' + str(int(rnd)/60) + ' Min ' + str(int(rnd)%60) + ' Sec'

time.sleep(int(rnd))

check_in()

#為了避免用戶設(shè)定一個(gè)時(shí)間后,程序每天都在同一時(shí)間點(diǎn)考勤,這里結(jié)合sleep和random實(shí)現(xiàn)在用戶設(shè)定時(shí)間上正向浮動(dòng)隨機(jī)時(shí)間進(jìn)行考勤

time.sleep(60)

........

........

check_time()def get_position(addr):

global longi

global lati

url = 'http://api.map.baidu.com/geocoding/v3/?address='+addr+'&output=json&ak='+api_key+'&callback=showLocation'

html = urllib2.urlopen(url.encode('utf-8')).read()

longi = re.search(r'lng":\d+.\d+',html).group().lstrip('lng":')

lati = re.search(r'lat":\d+.\d+',html).group().lstrip('lat":')

#調(diào)用百度地圖API獲取經(jīng)緯度信息,使用encode('utf-8')處理url可以避免中文亂碼問(wèn)題(需要注冊(cè)APIKEY)

運(yùn)行效果

總結(jié)

本文分享了筆者利用python編寫(xiě)某OA系統(tǒng)自動(dòng)考勤程序的過(guò)程,包括對(duì)系統(tǒng)邏輯的分析、程序結(jié)構(gòu)的介紹和關(guān)鍵代碼的解析等內(nèi)容。

程序最終實(shí)現(xiàn)了用戶自定義考勤時(shí)間、地址,并自動(dòng)根據(jù)地址獲取經(jīng)緯度(如地址為IP地址則不獲取),每天在指定時(shí)間以上述自定義信息進(jìn)行考勤。

歡迎各位大佬提出本程序的不足之處。注:考勤地址可自定義的漏洞已經(jīng)上報(bào)。

*本文作者:biubiugo,轉(zhuǎn)載請(qǐng)注明來(lái)自FreeBuf.COM

總結(jié)

以上是生活随笔為你收集整理的python实现oa系统_技术讨论 | 利用Python程序实现某OA系统的自动定位的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。