這個答案總結別人怎麼說以下,尤其是RedBaron,再加上加我用使用谷歌帳戶才能到StackOverflow的收件箱的方法。
使用Firefox的篡改數據的開發工具,並登錄到計算器,人們可以看到,OpenID的工作是這樣的:
- 的StackOverflow從給定服務(這裏谷歌),在發佈定義請求驗證數據;
- Google帳戶接管並檢查已存在的Cookie作爲身份驗證的證據;
- 如果找不到cookie,Google會請求驗證並設置cookie;
- 一旦cookie被設置,StackOverflow確認用戶的身份驗證。
以上總結了這個過程,實際上這個過程比較複雜,因爲許多重定向和cookie交換確實發生了。
由於通過程序再現相同的過程證明了某種程度上的困難(這可能只是我的文盲),特別是試圖追捕URL以調用所有語言環境細節等。我選擇先登錄Google帳戶,當之無愧的cookie,然後登錄到Stackoverflow,它將使用Cookie進行身份驗證。
這是通過使用以下Python模塊完成的:urllib,urllib2,cookielib和BeautifulSoup。
這是(簡化)代碼,它不是完美的,但它的確有用。擴展版本可在Github上找到。
#!/usr/bin/env python
import urllib
import urllib2
import cookielib
from BeautifulSoup import BeautifulSoup
from getpass import getpass
# Define URLs
google_accounts_url = 'http://accounts.google.com'
authentication_url = 'https://accounts.google.com/ServiceLoginAuth'
stack_overflow_url = 'https://stackoverflow.com/users/authenticate'
genuwine_url = 'https://stackoverflow.com/inbox/genuwine'
# Build opener
jar = cookielib.CookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(jar))
def request_url(request):
'''
Requests given URL.
'''
try:
response = opener.open(request)
except:
raise
return response
def authenticate(username='', password=''):
'''
Authenticates to Google Accounts using user-provided username and password,
then authenticates to StackOverflow.
'''
# Build up headers
user_agent = 'Mozilla/5.0 (Ubuntu; X11; Linux i686; rv:8.0) Gecko/20100101 Firefox/8.0'
headers = {'User-Agent' : user_agent}
# Set Data to None
data = None
# Build up URL request with headers and data
request = urllib2.Request(google_accounts_url, data, headers)
response = request_url(request)
# Build up POST data for authentication
html = response.read()
dsh = BeautifulSoup(html).findAll(attrs={'name' : 'dsh'})[0].get('value').encode()
auto = response.headers.getheader('X-Auto-Login')
follow_up = urllib.unquote(urllib.unquote(auto)).split('continue=')[-1]
galx = jar._cookies['accounts.google.com']['/']['GALX'].value
values = {'continue' : follow_up,
'followup' : follow_up,
'dsh' : dsh,
'GALX' : galx,
'pstMsg' : 1,
'dnConn' : 'https://accounts.youtube.com',
'checkConnection' : '',
'checkedDomains' : '',
'timeStmp' : '',
'secTok' : '',
'Email' : username,
'Passwd' : password,
'signIn' : 'Sign in',
'PersistentCookie' : 'yes',
'rmShown' : 1}
data = urllib.urlencode(values)
# Build up URL for authentication
request = urllib2.Request(authentication_url, data, headers)
response = request_url(request)
# Check if logged in
if response.url != request._Request__original:
print '\n Logged in :)\n'
else:
print '\n Log in failed :(\n'
# Build OpenID Data
values = {'oauth_version' : '',
'oauth_server' : '',
'openid_username' : '',
'openid_identifier' : 'https://www.google.com/accounts/o8/id'}
data = urllib.urlencode(values)
# Build up URL for OpenID authetication
request = urllib2.Request(stack_overflow_url, data, headers)
response = request_url(request)
# Retrieve Genuwine
data = None
request = urllib2.Request(genuwine_url, data, headers)
response = request_url(request)
print response.read()
if __name__ == '__main__':
username = raw_input('Enter your Gmail address: ')
password = getpass('Enter your password: ')
authenticate(username, password)
PS:我已經將這個帖子標記爲主持人關於故意複製的注意。 – Benjamin