2010-10-08 45 views
1

我在webpy的開發Web服務器上使用python-openid測試OpenID身份驗證。通過Yahoo!和myOpenID,我一直收到失敗響應消息服務器拒絕check_authentication。奇怪的是,我也收到了正確的openid.identity在其他方面成功的OpenID登錄FailureResponse:服務器被拒絕check_authentication

Google的相同類型的身份驗證正常工作(@https://www.google.com/accounts/o8/ud ...)。一方面,這讓我有信心,我正在做正確的事情,但另一方面,這種不一致使我感到困惑。

return_to & trust_root都是localhost:8080,這可能與它有關。

下面是我用來將用戶發送給Yahoo!的代碼。驗證:在這種情況下

def POST(self): 
    post_data = web.input() 
    if post_data.has_key('openid_identifier'): 
     openid_identifier = post_data.get('openid_identifier') 
     c = Consumer(session, openid.store.memstore.MemoryStore()) 
     auth = c.begin(openid_identifier) 
     auth_url = auth.redirectURL('http://localhost:8080', return_to='http://localhost:8080/authenticate') 
     raise web.seeother(auth_url) 
    return post_data 

auth_url設置爲(格式爲方便閱讀):

https://open.login.yahooapis.com/openid/op/auth? 
openid.assoc_handle=cYSO3wJSjQa3ewmRpaQz3YodzqjosP1ta.4TVzumqlLpAFM7oWci6K9bMKG4uuqZ.5m.fY7Wp8BWfQ1eR_soHWpJ6gCsKtxi_7Bqi22T5RUcMIuQBVjpGFSjc_kRY2k-& 
openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select& 
openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select& 
openid.mode=checkid_setup& 
openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0&openid.realm=http%3A%2F%2Flocalhost%3A8080& 
openid.return_to=http%3A%2F%2Flocalhost%3A8080%2Fauthenticate%3Fjanrain_nonce%3D2010-10-08T02%253A56%253A04ZrxAI 

這裏的處理程序看起來像在返回URL的內容:

def GET(self): 
    data = web.input() 
    c = Consumer(session, openid.store.memstore.MemoryStore()) 
    result = c.complete(dict(data), current_url='http://localhost:8080/authenticate') 
    if result.status == SUCCESS: 
     openid_identity = data.get('openid.identity') 
     ... 
    render = web.template.render('templates/', base='layout') 
    return render.error(...) 

result設置爲<openid.consumer.consumer.FailureResponse id=None message='Server denied check_authentication'>,data(返回上的查詢參數)如下設置:

<Storage {'openid.op_endpoint': u'https://open.login.yahooapis.com/openid/op/auth', 
'openid.sig': u'yCHffpHs2Whtw9p1gPzC+ToQJ0k=', 
'openid.ns': u'http://specs.openid.net/auth/2.0', 
'janrain_nonce': u'2010-10-08T02:56:04ZrxAIWh', 
'openid.return_to': u'http://localhost:8080/authenticate?janrain_nonce=2010-10-08T02%3A56%3A04ZrxAIWh', 
'openid.pape.auth_level.nist': u'0', 
'openid.claimed_id': u'https://me.yahoo.com/a/d3eEQZAWydfmtDwaGB2vBEVU4vIMLsez#1ac56', 
'openid.mode': u'id_res', 
'openid.realm': u'http://localhost:8080', 
'openid.response_nonce': u'2010-10-08T02:55:52ZRLNmEd7aWiaGWjHfhqEQs2Fxj3.nXdwciA--', 
'openid.signed': u'assoc_handle,claimed_id,identity,mode,ns,op_endpoint,response_nonce,return_to,signed,pape.auth_level.nist', 
'openid.identity': u'https://me.yahoo.com/a/d3eEQZAWydfmtDwaGB2vBEVU4vIMLsez', 
'openid.assoc_handle': u'cYSO3wJSjQa3ewmRpaQz3YodzqjosP1ta.4TVzumqlLpAFM7oWci6K9bMKG4uuqZ.5m.fY7Wp8BWfQ1eR_soHWpJ6gCsKtxi_7Bqi22T5RUcMIuQBVjpGFSjc_kRY2k-'}> 

那肯定對我來說看起來不是一個失敗的迴應。請注意,設置了openid.identity。是的,那是我在雅虎上的OpenID身份。

我不確定從哪裏拿這個。任何建議的話?

+0

如果服務器拒絕了check_authentication,或者它返回了false,則應該假定用戶沒有進行身份驗證。 check_authentication用於驗證您獲得的數據來自OP,而不是來自任何其他來源。但是我不知道,在這種情況下可能會發生什麼。 – Mewp 2010-10-08 17:43:48

+0

在這種情況下,我有一個關聯句柄,所以'check_authentication'甚至不應該嘗試。我必須錯誤地使用python-openid API,但我無法弄清楚。 – 2010-10-10 04:45:38

+0

你看過'django-openid-auth'和'django-openid-consumer'嗎?包含有關如何處理OpenID請求的調試示例。 – 2010-10-11 15:42:31

回答

3

消費者需要一個數據存儲來維護髮現和身份驗證之間的狀態。我正在使用的商店openid.store.memstore.MemoryStore()實際上並未維持請求之間的狀態。它只在一個過程中保持狀態 - 正如你對「記憶」(杜)所期望的那樣。必須改變的一點是在GET和POST處理程序中創建消費者。

這是錯誤的方式來創建消費者:

# BAD: MemoryStore() has a short memory -- within the process only 
c = Consumer(session, openid.store.memstore.MemoryStore()) 

而這裏創造了消費者的正確方法:

# GOOD: MySQL has a long memory -- across processes 
db = web.database(dbn='mysql', db='somedb', user='someuser', pw='') 
conn = db._db_cursor().connection 
cstore = sqlstore.MySQLStore(conn, 'openid_associations', 'openid_nonces') 
c = Consumer(session, cstore) 

我想這有助於記住你的assoc命令處理和隨機數。我一定在這裏呆了10個小時,所以我希望這可以幫助下一個人(或加侖)避免這樣做。

這將是我贏得的第一個賞金 - 我自己的。活泉!

離別注意:這假定您已經設置了您的數據庫中的OpenID表,這看起來應該像這樣在MySQL:

create table openid_nonces (
    server_url blob not null, 
    timestamp integer not null, 
    salt char(40) not null, 
    primary key (server_url(255), timestamp, salt) 
) engine=InnoDB; 

create table openid_associations (
    server_url blob not null, 
    handle varchar(255) not null, 
    secret blob not null, 
    issued integer not null, 
    lifetime integer not null, 
    assoc_type varchar(64) not null, 
    primary key (server_url(255), handle) 
) engine=InnoDB; 

檢查的the documentation的openid.store.sqlstore節相關的SQL語句您的特定商店。

相關問題