1. 程式人生 > >對OAuth1.0協議的理解

對OAuth1.0協議的理解

OAuth(開放授權)是一個開放標準,允許使用者讓第三方應用訪問該使用者在某一網站上儲存的私密的資源(如照片,視訊,聯絡人列表),而無需將使用者名稱和密碼

研究的是OAuth1.0,因為2.0褒貶不一,連創始人都宣佈脫離關係了。。。而1.0基本各個大網站都支援的不錯

具體舉個例子:

比如我們手機用蝦米app來聽歌,想要登入蝦米但又不想註冊一個新的賬號,可以選擇第三方登入,也就是用微博號登入。那麼自然不能直接把微博的使用者名稱密碼告訴蝦米,不然誰知道會發生什麼事情呢?所以就用到了OAuth. 蝦米將頁面轉到新浪提供的登入頁面,我們在新浪登入頁面輸入使用者名稱和密碼,進行身份驗證,然後新浪會給蝦米一個token,如下(僅供參考格式,不要在意值是多少。。。):

oauth_consumer_key="0685bd9184jfhq22",
                oauth_token="ad180jjd733klru7",
                oauth_signature_method="HMAC-SHA1",
                oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D",
                oauth_timestamp="137131200",
                oauth_nonce="4572616e48616d6d65724c61686176",
                oauth_version="1.0"
之後的各種操作就可以利用以上的各個變數來進行身份驗證,這樣蝦米也不知道使用者的使用者名稱和密碼,但是可以利用微博賬號來作為新的使用者身份。

注意:token指的是上面所有內容,包含所有的key-value,而oauth_token則是指token裡面的一項,用於唯一標識使用者。這點我之前矛盾了很久,到底說的token和oauth_token有沒有區別。。。

下面具體來講oauth身份認證的幾個步驟(結合之前的例子):

0)首先第三方app一定要去相應的網站註冊。如上面的例子中,第三方式蝦米app,resource owner是新浪微博,也就是蝦米需要告訴新浪微博我要來使用你裡面的資料,所以註冊一下跟你說一聲,這樣蝦米app會得到新浪微博返回的一個consumer_key和consumer_secret. 這兩個也就是蝦米app在新浪微博的一個身份,使用者名稱+密碼(當然為了安全,密碼應該是通過郵件等方式傳送給蝦米app的)。這第0步不是每次身份認證都要用的,只是在app開發時,開發者需要做這一步而已。

1)蝦米app向新浪微博申請要一個token,說我打算訪問你的資料啦。申請的時候蝦米app傳送如下的http請求給新浪微博:

consumer secret - "MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98"
oauth_consumer_key - GDdmIQH6jhtmLUypg82g
oauth_nonce - QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk
oauth_signature_method - HMAC-SHA1
oauth_timestamp - 1272323042
oauth_version - 1.0
注意注意:第一個consumer secret並不是http裡面的內容,這是之後用來生成簽名的(因為oauth1.0是針對http設計的,故傳遞secret不安全,所以採用簽名機制)。解釋一下幾個變數的含義:這裡的secret就是指第0步註冊後得到的蝦米app的密碼。consumer_key就是剛才第0步得到的,nonce是number used once(具體形式有多種,可以數字可以字串),只要知道是和timestamp搭配來標識唯一就行了(防止一些攻擊),signature_method是產生簽名的方法,一般用HMAC-SHA1, timestamp一反面和nonce唯一標識token,另一方面用來保證token的實效性,version表示oauth版本。

然後我們利用上述資訊產生一個base string,如下(產生方法是http方法(get或者post)+網址(這裡指新浪微博網址)+上述各值):

POST&https%3A%2F%2Fapi.t.sina.com.cn%2Foauth%2Frequest_token&oauth_consumer_key%3DGDdmIQH6jhtmLUypg82g%26oauth_nonce%3DQP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1272323042%26oauth_version%3D1.0
由於我們還未獲取到oauth_token和oauth_token_secret,所以我們的BASE STRING裡沒有包含oauth_token和oauth_token_secret。

這個時候剛才提過的consumer_key就發揮作用了,用consumer_key作為key對base string進行HMAC-SHA1簽名,假設得到簽名為“8wUi7m5HFQy76nowoCThusfgB+Q=”,則我們的http請求如下:

oauth_nonce="QP70eNmVz8jvdPevU3oJD2AfF7R7odC2XJcn4XlZJqk",  oauth_signature_method="HMAC-SHA1", oauth_timestamp="1272323042", oauth_consumer_key="GDdmIQH6jhtmLUypg82g", oauth_signature="8wUi7m5HFQy76nowoCThusfgB%2BQ%3D", oauth_version="1.0"
然後新浪那邊利用我們傳過去的這些資訊對app進行身份驗證,即在此利用上述資訊產生簽名,核對簽名(因為新浪微博是有蝦米app註冊時的密碼的,這樣就達到了不用傳遞密碼的效果,保證安全),如果app身份正確,則返回如下內容:
oauth_token=8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc&oauth_token_secret=x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA
即返回一個oauth_token和oauth_token_secret

2)由於上述token只是一個臨時token,蝦米app需要使用者授權

蝦米app會將頁面轉到授權網址,並攜帶oauth_token引數,如下:

然後需要使用者輸入他在新浪微博的使用者名稱和密碼,正確後新浪微博返回以下結果(注意verifier是1.0a加入的,為了解決OAuth Session Fixation Attack):

oauth_token=8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc&oauth_verifier=pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY

3)第三步蝦米app用上述資訊去把之前的臨時token變成access token(可以訪問資源的token)

目前已有資訊為:
oauth_consumer_key - GDdmIQH6jhtmLUypg82g
    oauth_nonce - 9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8
    oauth_signature_method - HMAC-SHA1
    oauth_token - 8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc
    oauth_timestamp - 1272323047
    oauth_verifier - pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY
    oauth_version - 1.0
和第一步一樣,利用上述資訊產生一個base string,如下:
POST&https%3A%2F%2Fapi.t.sina.com.cn%2Foauth%2Faccess_token&oauth_consumer_key%3DGDdmIQH6jhtmLUypg82g%26oauth_nonce%3D9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1272323047%26oauth_token%3D8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc%26oauth_verifier%3DpDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY%26oauth_version%3D1.0
然後接著進行簽名,這裡的key為oauth_consumer_secret+oauth_token_secret,兩者拼接成一個key,對上述base string進行簽名。得 “PUw/dHA4fnlJYM6RhXk5IU/0fCc=”,於是傳送的http請求如下:
oauth_nonce="9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1272323047", oauth_consumer_key="GDdmIQH6jhtmLUypg82g", oauth_token="8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc", oauth_verifier="pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY", oauth_signature="PUw%2FdHA4fnlJYM6RhXk5IU%2F0fCc%3D", oauth_version="1.0"
然後新浪微博伺服器端再次利用簽名技術,對此進行身份驗證,正確的話則返回:
oauth_token=819797-Jxq8aYUDRmykzVKrgoLhXSq67TEa5ruc4GJC2rWimw&oauth_token_secret=J6zix3FfA9LofH0awS24M3HcBYXO5nI1iYe8EfBA&user_id=819797&screen_name=openapi
那麼這裡的oauth_token就是access token了,secret也就是access token的密碼

4)蝦米app利用access token就可以訪問使用者資源了,還是像上述一樣,利用access token構造簽名,然後申請資源,伺服器驗證身份後,返回使用者的資料(比如微博頭像等等),就不重複講了

總結:oauth1.0分成3步:1)request token 2) authorize token 3) access token

優點:利用簽名技術保證安全

缺點:太過繁雜,不過貌似是由於http不安全只能設計成這樣。。。

嗯,暫時就先說到這裡吧。。。