This question has been asked here before。对于提问者和回答者来说,接受的答案可能是显而易见的 - 但不是对我而言。我已就上述问题发表评论以获得更多精确度,但没有回应。 I also approached the meta Q&A寻求如何从他们的坟墓中提出问题的帮助,也没有得到答案。
以上问题的答案是:
从客户端的角度来看,OpenID登录与任何其他基于Web的登录非常相似。客户端没有定义的协议;它是一个普通的Web会话,根据您的OpenID提供程序而有所不同。出于这个原因,我怀疑是否存在任何此类库。您可能需要自己编写代码。
我已经知道如何log onto a website with Python使用Urllib2模块。但这还不足以让我猜测如何对OpenID进行身份验证。
我实际上是想获得my StackOverflow inbox in json format,我需要登录。
有人可以提供一个简短的介绍或链接到一个很好的教程如何做到这一点?
答案 0 :(得分:11)
好吧,我自己对OpenID了解不多,但你的帖子(以及赏金!!)让我感兴趣。
This link告诉OpenID身份验证序列的确切流程(Atleast for v1.0。新版本为2.0)。根据我的想法,步骤将类似于
This link讲述了OpenID中的各种响应及其含义。因此,当您的代码成为您的客户时,它可能会派上用场。
来自维基页面的链接OpenID Explained
编辑:使用Tamper Data Add on for Firefox,可以构建以下事件序列。
我建议您开始编写python客户端并仔细研究响应。在大多数情况下,它将是一系列302,用户干预最少(填写您的Google用户名和密码并允许网站页面除外)。
然而,为了方便起见,您可以使用浏览器登录SO,复制所有cookie值并使用urllib2发出请求并设置cookie值。
当然,如果您在浏览器上注销,则必须再次登录并更改python程序中的cookie值。
答案 1 :(得分:6)
我知道这很接近考古学,挖了两年的帖子,但我刚从经过验证的答案中写了一个新的增强版代码,所以我觉得在这里分享它可能很酷,因为这个问题/ answers对我来说是一个很好的帮助。
所以,这里有什么不同:
requests
库是urllib2
; 这是代码:
#!/usr/bin/env python
import sys
import urllib
import requests
from BeautifulSoup import BeautifulSoup
def get_google_auth_session(username, password):
session = requests.Session()
google_accounts_url = 'http://accounts.google.com'
authentication_url = 'https://accounts.google.com/ServiceLoginAuth'
stack_overflow_url = 'http://stackoverflow.com/users/authenticate'
r = session.get(google_accounts_url)
dsh = BeautifulSoup(r.text).findAll(attrs={'name' : 'dsh'})[0].get('value').encode()
auto = r.headers['X-Auto-Login']
follow_up = urllib.unquote(urllib.unquote(auto)).split('continue=')[-1]
galx = r.cookies['GALX']
payload = {'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}
r = session.post(authentication_url, data=payload)
if r.url != authentication_url: # XXX
print "Logged in"
else:
print "login failed"
sys.exit(1)
payload = {'oauth_version' : '',
'oauth_server' : '',
'openid_username' : '',
'openid_identifier' : ''}
r = session.post(stack_overflow_url, data=payload)
return session
def get_so_auth_session(email, password):
session = requests.Session()
r = session.get('http://stackoverflow.com/users/login')
fkey = BeautifulSoup(r.text).findAll(attrs={'name' : 'fkey'})[0]['value']
payload = {'openid_identifier': 'https://openid.stackexchange.com',
'openid_username': '',
'oauth_version': '',
'oauth_server': '',
'fkey': fkey,
}
r = session.post('http://stackoverflow.com/users/authenticate', allow_redirects=True, data=payload)
fkey = BeautifulSoup(r.text).findAll(attrs={'name' : 'fkey'})[0]['value']
session_name = BeautifulSoup(r.text).findAll(attrs={'name' : 'session'})[0]['value']
payload = {'email': email,
'password': password,
'fkey': fkey,
'session': session_name}
r = session.post('https://openid.stackexchange.com/account/login/submit', data=payload)
# check if url changed for error detection
error = BeautifulSoup(r.text).findAll(attrs={'class' : 'error'})
if len(error) != 0:
print "ERROR:", error[0].text
sys.exit(1)
return session
if __name__ == "__main__":
prov = raw_input('Choose your openid provider [1 for StackOverflow, 2 for Google]: ')
name = raw_input('Enter your OpenID address: ')
pswd = getpass('Enter your password: ')
if '1' in prov:
so = get_so_auth_session(name, pswd)
elif '2' in prov:
so = get_google_auth_session(name, pswd)
else:
print "Error no openid provider given"
r = so.get('http://stackoverflow.com/inbox/genuwine')
print r.json()
代码也可以github gist
的形式提供HTH
答案 2 :(得分:3)
此答案总结了其他人在下面所说的内容,尤其是RedBaron,并添加了一个我用来使用Google帐户访问StackOverflow收件箱的方法。
使用Firefox的Tamper Data开发人员工具并登录到StackOVerflow,可以看到OpenID以这种方式工作:
以上总结了这个过程,实际上更复杂,因为确实发生了许多重定向和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)
答案 3 :(得分:0)
您需要在任何“登录”页面上实现cookie,在Python中使用cookiejar。例如:
jar = cookielib.CookieJar()
myopener = urllib2.build_opener(urllib2.HTTPCookieProcessor(jar))
#myopener now supports cookies.
....
答案 4 :(得分:0)
我制作了一个简单的脚本,使用Mozilla Firefox cookie登录到stackoverflow.com。它不是完全自动化的,因为你需要手动登录,但这是我设法做到的。
Scipt对于FF的最新版本是实际的(我使用的是8.0.1),但你需要获得最新的sqlite dll,因为python 2.7附带的默认版本无法打开DB。你可以在这里得到它:http://www.sqlite.org/sqlite-dll-win32-x86-3070900.zip
import urllib2
import webbrowser
import cookielib
import os
import sqlite3
import re
from time import sleep
#login in Firefox. Must be default browser. In other cases log in manually
webbrowser.open_new('http://stackoverflow.com/users/login')
#wait for user to log in
sleep(60)
#Process profiles.ini to get path to cookies.sqlite
profile = open(os.path.join(os.environ['APPDATA'],'Mozilla','Firefox','profiles.ini'), 'r').read()
COOKIE_DB = os.path.join(os.environ['APPDATA'],'Mozilla','Firefox','Profiles',re.findall('Profiles/(.*)\n',profile)[0],'cookies.sqlite')
CONTENTS = "host, path, isSecure, expiry, name, value"
#extract cookies for specific host
def get_cookies(host):
cj = cookielib.LWPCookieJar()
con = sqlite3.connect(COOKIE_DB)
cur = con.cursor()
sql = "SELECT {c} FROM moz_cookies WHERE host LIKE '%{h}%'".format(c=CONTENTS, h=host)
cur.execute(sql)
for item in cur.fetchall():
c = cookielib.Cookie(0, item[4], item[5],
None, False,
item[0], item[0].startswith('.'), item[0].startswith('.'),
item[1], False,
item[2],
item[3], item[3]=="",
None, None, {})
cj.set_cookie(c)
return cj
host = 'stackoverflow'
cj = get_cookies(host)
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
response = opener.open('http://stackoverflow.com').read()
# if username in response - Auth successful
if 'Stanislav Golovanov' in response:
print 'Auth successful'