Python實現網站模擬登錄

1、實驗簡介

1.1 基本介紹

本實驗中咱們將經過分析登錄流程並使用 Python 實現模擬登錄到一個實驗提供的網站,在實驗過程當中將學習並實踐 Python 的網絡編程,Python 實現模擬登錄的方法,使用 Firefox 抓包分析插件分析網絡數據包等知識。html

模擬登陸能夠幫助用戶自動化完成不少操做,在不一樣場合下有不一樣的用處,不管是自動化一些平常的繁瑣操做仍是用於爬蟲都是一項很實用的技能。本課程經過 Firefox 和 Python 來實現,環境要求以下:前端

  • Python 庫:urllib, urllib2, cookielib, Django
  • Firefox 要求:裝有 live http header插件 (已提供)

1.2 知識點

本項目中咱們將學習並實踐如下知識點:python

  1. 網站登陸流程分析
  2. Python 網絡編程基礎
  3. Firefox 抓包分析插件 Live http header
  4. Python 模擬登錄實現流程

1.3 實驗材料

爲了節省時間,實驗用到的材料已經提早製做完成,能夠按照材料清單中給出的連接下載。web

實驗網站源碼:
http://labfile.oss.aliyuncs.com/courses/640/mysite.zip FireFox抓包插件: http://labfile.oss.aliyuncs.com/courses/640/live_http_headers.xpi 

1.4 實驗準備

1) 安裝抓包插件Live Http Headers

打開 Linux Xfce 終端並經過 wget 命令下載插件文件。下載成功後首選右鍵單擊xpi文件-->使用FireFox打開,以後按照界面提示安裝Live Http Header插件:正則表達式

安裝Live Http Header插件

點擊安裝

按照提示重啓以後,經過 打開菜單-->附加組件-->擴展 找到安裝好的插件,點擊 首選項,勾選 Config 選項卡中的Open LiveHTTPHeaders in a new tab 選項以方便使用。django

插件設置

2)啓動web應用

因爲實驗樓會員環境中啓動的 WebIDE 會佔用 8000 端口,因此若是是實驗樓會員,請先中止 codebox 進程後再部署下面的 Web 應用。編程

使用 ps -aux | grep codebox 查詢得到 codebox 的進程號,而後使用 kill -9 進程號 中止 codebox 進程。執行過程見下圖:api

此處輸入圖片的描述

首先安裝demo依賴的web框架django,並測試是否安裝成功:瀏覽器

$ sudo pip install django
$ python
>>> import django >>> django.VERSION (1, 10, 0, u'final', 1) 

再經過unzip命令解壓網站文件,並啓動網站服務。安全

$ wget http://labfile.oss.aliyuncs.com/courses/640/mysite.zip $ unzip mysite.zip $ cd mysite $ ./manage.py runserver 

啓動成功後在瀏覽器中輸入 http://localhost:8000/polls 看到登陸頁面表示啓動成功。

解壓並啓動web應用

2、分析登陸過程

要經過編程實現登陸,首先須要理解通常Web應用的登錄過程。

不一樣的網站和應用登陸的安全性和複雜性都不一樣,所以它們的登陸實現過程天然會存在差別,儘管如此,最基礎,核心的過程依然是相同的。對於複雜的登陸過程(例如淘寶),對請求包和響應包的分析能力是很重要的。

瀏覽器有自帶的分析工具,可是界面比較窄,考慮到實驗環境界面較小,本課程選擇了 Live Http Header,同窗們能夠在本地選用任何本身喜歡的工具進行分析。咱們先經過示例頁面分析一下簡單的登錄過程熟悉下分析過程。

2.1 抓取請求

  1. 輸入http://localhost:8000/polls打開登陸頁。
  2. 打開live http header(F10->工具->Live Http Header)。
  3. 輸入用戶名和密碼(都是shiyanlou)並提交表單,登入系統。
  4. 切換到Live Http Header頁面查看http請求和響應信息

2.2原理分析

Live http Headers插件的Headers選項卡中會列出抓取到的全部的http請求和響應頭,一次請求的url、請求和響應之間經過空行隔開,不一樣的請求之間經過虛線隔開。在按照2.1中的步驟登入系統後,咱們在列表中看到了2個請求。第一個請求核心內容以下(還記得HTTP協議的內容嗎?):

POST /polls/login HTTP/1.1 //請求行 ******************** //此處省略其餘請求頭 Content-Type: application/x-www-form-urlencoded //請求實體類型 Content-Length: 41 //實體信息長度 name=shiyanlou&pwd=shiyanlou&commit=Login //實體內容 HTTP/1.0 302 Found //響應行,302重定向 Location: . //重定向的路徑 ******************** //此處省略其餘響應頭 Set-Cookie: sessionid=aped4pzerxjgd3db0ixw0dowkgrdpsxb;expires=Thu, 15-Sep-2016 15:04:28 GMT; httponly; Max-Age=1209600; Path=/ //響應頭,服務器回寫cookie 

爲何是2個請求而不是1個呢?經過分析登陸請求發現,登錄成功以後服務器發送了302重定向響應,服務器要求瀏覽器從新請求首頁,這就產生了第二個請求。再來分析第二個請求,能夠看到它相比登陸請求多了一個請求頭:

Cookie: sessionid=aped4pzerxjgd3db0ixw0dowkgrdpsxb 

這個 Cookie 中的 sessionid 是從上一個響應頭中的 Set-Cookie 行中獲取,因此值相同。session的意思是會話,服務器經過session存儲和維護與單個用戶之間的會話信息。不一樣的用戶在服務器端有不一樣的session,而且爲了確保正常通訊,每一個用戶的session都是惟一的。登陸過程其實就是在驗證用戶登陸信息後在session中存儲用戶登陸標識的過程。在開發web應用時,「登錄成功」與「在session中存儲用戶登陸標識」是等價的。整個登陸流程以下圖所示:

登陸流程

那麼問題來了,服務器究竟是如何區別不一樣用戶的session的?爲何登錄成功會後要回寫cookie呢?答案就是sessionid!每一個用戶的session都有獨立的、惟一的編號sessionid用來標識用戶身份。用戶登陸後,服務器經過從用戶的session中讀取登陸標識來進行身份認證,所以必需要知道sessionid來訪問用戶的session,而使用cookie正是知足這個需求的方法。服務器將須要瀏覽器存儲的信息經過Set-Cookie響應頭髮送給瀏覽器,瀏覽器會將cookie存儲在本地,並在每次訪問該網站時附帶發送指定的cookie以知足服務器的需求,而經過cookie存儲sessionid就是其中的一種應用。

2.3小結

對於服務器來講,登陸=驗證+寫session。對於瀏覽器來講,登陸=發送登陸信息+獲取帶sessionid的cookie。能夠說,只要得到了sessionid,就算實現了模擬登陸。有了它咱們即可以遊離於系統之中。

3、使用Python實現登陸(簡單實例)

理解了登陸過程的原理和細節以後,開始用Python來編寫模擬登錄程序吧。在任意目錄下新建login_base.py文件,使用你喜歡的編輯器打開。實現流程以下:

3.1導入模塊

不要忘記編寫文件頭、導入必要的依賴模塊哦

#!/usr/bin/python #-*- coding:utf-8 -*- import urllib import urllib2 import cookielib 

3.2構造登陸請求

一個http請求由3部分組成:請求url、請求頭以及請求實體(附帶數據)。在Python的urllib2庫中,由urllib2.Request對象描述一個request。其中url是一個字符串、請求頭是一個dict,key是請求頭名稱,value是請求頭的內容。至於請求數據就要分具體狀況了,在表單提交這種場景下,請求數據類型爲application/x-www-form-urlencoded,意思就是通過url編碼的表單數據,數據的組織形式是key=value,多組鍵值對之間用&分隔。登陸請求的實體部分以下:

Content-Type: application/x-www-form-urlencoded //請求實體類型 Content-Length: 41 //實體信息長度 name=shiyanlou&pwd=shiyanlou&commit=Login //實體內容 

此時,咱們只須要使用dict來存儲鍵值對,再用urllib.urlencode()方法進行編碼就能夠了。最後建立urllib2.Request對象,所有代碼以下:

url = 'http://localhost:8000/polls/login' values = { 'name':'shiyanlou', 'pwd':'shiyanlou', 'commit':'Login' } headers = {'Referer':'http://localhost:8000/polls/show_login'} request = urllib2.Request(url,data=urllib.urlencode(values),headers=headers) 

附加參數

須要注意的是,在瀏覽器頁面操做時,用戶只須要輸入用戶名和密碼,看起來好像只須要提交2個參數到服務器。但實際上前端頁面通常都會提交其餘元參數到服務器,大多數都是與服務端的訪問api設計有關,還有一些控制參數。一個登陸請求包含5個以上的參數是再正常不過的事情,但並非每個參數都是登陸所必要的,有些參數即便沒有也不會影響正常登陸。在實驗demo中,commit這個參數就是必須提交的,不然會登陸失敗。

防盜鏈

Web 應用的資源都是有url的,只要得到了url就可以在任何地方引用。聽起來很方便,但這可能會致使你的資源被別人盜用。爲了訪問量,把本身辛辛苦苦PS的一張美照放到我的站點上,卻被別人的站點給引用走了,豈不是很氣人?而HTTP的請求頭Referer就是爲了解決這類問題而生,Referer描述了當前請求的發出者,也就是引用者,服務器能夠經過Referer來判斷當前的引用者是不是合法的引用者從而決定是否返回請求的資源。考慮到必定的安全性,通常的網站登陸都會限制Referer域來防止非法登陸。所以,爲了成功登陸,咱們須要在request頭中填寫Referer頭,內容從抓取的請求頭中照搬來便可。

通常狀況下,打開url默認使用urllib2的urlopen()函數,可是它不能處理cookie。這裏咱們須要本身建立可以存儲cookie的opener。python內置有cookielib庫來處理cookie,其中的MozillaCookieJar能夠將cookie存儲到文件中,並能夠從文件中讀取cookie。先建立MozillaCookieJar對象,再使用urllib2.HTTPCookieProcessor建立cookie處理器,最後使用urllib2.build_opener建立opener。接下來就能夠用opener發送請求並存儲cookie了。代碼以下:

# 建立opener cookies = cookielib.MozillaCookieJar('my_cookies.txt') # 指定cookie的存儲文件 cookie_handler = urllib2.HTTPCookieProcessor(cookies) opener = urllib2.build_opener(cookie_handler) # 發送請求 & 保存cookie response = opener.open(request) cookies.save() print response.code print response.read() 

若是登錄成功,就能夠在指定的文件my_cookies.txt中看到sessionid了。

localhost.local    FALSE / FALSE 1474019663 sessionid vejomjbliggkwblzfagobv3u8foik6am 

登陸系統只不過是一個開始,使用sessionid訪問系統服務纔是最終目的。舉一個簡單的例子,咱們的網站demo的首頁中由一個查詢系統當前時間的接口(在現實生活中多是更有用的,好比信息查詢),咱們在登陸後點擊它,能夠看到它的url是http://localhost:8000/polls/date,這是隻爲登陸用戶提供的服務。若是咱們如今返回首頁,退出登陸以後直接在地址欄中輸入這個url,頁面將會302重定向至登陸頁,沒法看到當前時間。

首頁圖片

查看當前時間

在咱們模擬登陸成功後,就能夠直接經過opener打開這個url來使用這項系統服務。代碼實現以下:

url2 = 'http://localhost:8000/polls/date' response2 = opener.open(url2) print response2.code print response2.read() 

若是有是在另一個py文件中使用這個cookie的話,再打開url以前須要先載入cookie:

# 載入cookie cookie = cookielib.MozillaCookieJar() cookie.load('my_cookies.txt') opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie)) 

固然,以上只是一個簡單的示例,只是爲了說明原理。實際應用中的請求中會有各類各樣的請求參數、元數據參數甚至是多樣的驗證cookie,只有理解了原理纔可以以不變應萬變。

4、高級登錄練習

是否是原理聽懂了,可是隻實現demo感受不夠過癮?咱們來一塊兒作一作下面這個稍微難一點的練習吧。

4.1題目

已知信息:

要求:

  • 模擬登錄成功並存儲cookie

4.2 過程分析提示

管理員的登陸請求的請求以下:

POST /admin/login/?next=/admin/ HTTP/1.1 Referer: http://localhost:8000/admin/login/?next=/admin/ Cookie: csrftoken=adxAiQKnRYgQoS4RmoooCesA7mBgJtwVnsd98nttE1arcBAnGwRbILLvWeS5xLfM Content-Type: application/x-www-form-urlencoded Content-Length: 137 csrfmiddlewaretoken=tsxs3KcOUt4ZdMg1gMBCKkNV8JTxZigaGHd1ThVUHwYA1vMxAU4pQR6QXBamNAZ1&username=admin&password=djangoadmin&next=%2Fadmin%2F HTTP/1.0 302 Found Vary: Cookie Last-Modified: Fri, 02 Sep 2016 09:24:46 GMT Location: /admin/ Content-Type: text/html; charset=utf-8 Set-Cookie: csrftoken=seowCkz5vprAPZbkqF7M4QuzYZPKgoUrsO5nE3WWxtYnc5NRKB34rmmrTAIDdCaK; expires=Fri, 01-Sep-2017 09:24:46 GMT; Max-Age=31449600; Path=/ Set-Cookie: sessionid=cb6z7xlu31uxt8kdupfh0td43ewhgvpx; expires=Fri, 16-Sep-2016 09:24:46 GMT; httponly; Max-Age=1209600; Path=/ 

不難觀察到登陸請求中附帶了csrftoken這個cookie,表單數據中必須提交csrfmiddlewaretoken,username,password這三個參數,最後的next參數是url中附帶的,不須要額外添加。必須獲得前兩個參數纔可以成功登錄,這兩個參數從名字上來看都用來做認證令牌,應該是由服務器生成的。其中的cookie確定是來自上一個response的回寫,而從csrfmiddlewaretoken的位置來看,應該是在登錄表單當中。註銷登錄,從新進入登陸頁面,點擊右鍵查看源代碼發現了這個輸入域(每次請求的值都是不一樣的):

<input type='hidden' name='csrfmiddlewaretoken' value='PSM5KbmRGdHraaVXK9UEzsWmLYlHxYjUPstWMUJIIheexgxu45QWWYOeGzeAuczd' /> 

這樣一來咱們的思路就很清晰了:

登陸做業實現流程

解析頁面可使用python的正則表達式re模塊或者是比較火的beautifulsoup庫。但願同窗們先本身動手挑戰一下,歡迎再課程回覆中和我討論,屆時我將提供登陸代碼。

5、總結&擴展

模擬登錄的關鍵是弄清楚登陸請求須要提交的參數,重點是要獲取帶有sessionid的cookie,最終目的是不受限制的訪問系統提供的有價值的服務。

只有分析清楚登錄過程才能達到最終目的,這就須要具有強的HTTP包分析能力,理解HTTP協議,並配合包分析工具(FireBug,Live Http Header,Burp Suite等)解析出關鍵參數,有時須要編輯和重發包來刪減掉沒必要要的多餘參數。下面給出一些提升的參考資料,學有餘力的同窗能夠深刻研究:

相關文章
相關標籤/搜索