Câu trả lời này tóm tắt những gì người khác đã nói dưới đây, đặc biệt là RedBaron, cộng thêm một phương pháp tôi đã sử dụng để có được StackOverflow Inbox sử dụng Tài khoản Google.
Sử dụng công cụ nhà phát triển Tamper dữ liệu của Firefox và đăng nhập vào Stackoverflow, người ta có thể thấy rằng OpenID làm việc theo cách này:
- StackOverflow yêu cầu xác thực từ một dịch vụ nhất định (ở đây của Google), được định nghĩa trong posted dữ liệu;
- Tài khoản Google tiếp quản và kiểm tra cookie hiện có làm bằng chứng xác thực;
- Nếu không tìm thấy cookie, Google yêu cầu xác thực và đặt cookie;
- Khi cookie được đặt, StackOverflow xác nhận xác thực của người dùng.
Tổng hợp ở trên, quá trình này thực tế phức tạp hơn vì nhiều chuyển hướng và trao đổi cookie thực sự xảy ra.
Vì sao chép cùng một quy trình được chứng minh bằng cách nào đó khó khăn (và đó có thể chỉ là mù chữ của tôi), đặc biệt là tìm kiếm các URL để gọi với tất cả các đặc điểm địa phương, v.v. Tôi đã chọn đăng nhập vào Tài khoản Google trước, cũng xứng đáng cookie và sau đó đăng nhập vào Stackoverflow, mà sẽ sử dụng cookie để xác thực.
Điều này được thực hiện đơn giản bằng cách sử dụng các mô-đun Python sau: urllib, urllib2, cookielib và BeautifulSoup.
Đây là mã (đã được đơn giản hóa), nó không hoàn hảo, nhưng nó thực hiện thủ thuật. Phiên bản mở rộng có thể được tìm thấy trên 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: Tôi đã gắn cờ bài đăng này đã dành cho sự chú ý của người kiểm duyệt đối với việc cố ý sao chép. – Benjamin