Django OAuth Toolkit
使用說明
B依托Django OAuth Toolkit, 具備作為OAuth2.0服務器能力, 第三方網站/系統(tǒng)/服務/APP, 可以利用該能力, 獲取用戶登錄信息, 各類資源.
假設你擁有一個系統(tǒng)A, 希望在系統(tǒng)A的導航條中增加一個按鈕, “使用B登錄”, 點擊后, 用戶可以利用B帳號登錄系統(tǒng)A, 并獲取用戶信息和B可向系統(tǒng)A暴露的其他信息.
具體來說, 用戶會訪問系統(tǒng)A(a), 點擊”使用B登錄”, 并被跳轉到B登錄頁(b), 如果用戶沒有登錄B, 需要輸入用戶名密碼, 否則用戶被詢問是否允許使用B帳號登錄系統(tǒng)A(c), 用戶點擊允許, 并跳轉回系統(tǒng)A(d), 系統(tǒng)A獲得Token, 可以訪問用戶信息等B接口(e).
了解一些背景知識
OAuth2.0是一種非常通用的工業(yè)級授權方式(OAuth 2.0 is the industry-standard protocol for authorization.) 如果你從未聽過, 可以參考下列資料做一個粗略了解:
在B注冊系統(tǒng)A
注冊并登錄B.
打開OAuth應用注冊頁面 你的服務地址/oauth2/applications/, 點New Application
其中Name填自己的應用名稱, Client id和Client secret可以用自動生成的.
-
name:應用名稱
-
Client id、Client secret自動生成
-
Client type :公開還是機密
-
Authorization grant type 一共有四種
-
授權碼(authorization-code):指的是第三方應用先申請一個授權碼,然后再用該碼獲取令牌,這種方式是最常用的流程,安全性也最高,它適用于那些有后端的 Web 應用。一般針對于用戶。此種方式見后面詳細介紹。

-
隱藏式(implicit):有些 Web 應用是純前端應用,沒有后端。這時就不能用上面的方式了,必須將令牌儲存在前端
-
密碼式(password):如果你高度信任某個應用,也允許用戶把用戶名和密碼,直接告訴該應用。該應用就使用你的密碼,申請令牌
-
客戶端憑證(client credentials):最后一種方式是憑證式(client credentials),適用于沒有前端的命令行應用,即在命令行下請求令牌。這種方式給出的令牌,是針對第三方應用的,而不是針對用戶的,即有可能多個用戶共享同一個令牌。
可直接通過client_id和secret直接獲取token
# body { "client_id": "xxx", "client_secret": "xxx", "redirect_uri": "http://django-oauth-toolkit.herokuapp.com/consumer/exchange/", "grant_type": "client_credentials" }
-
-
Redirect uris:訪問以后跳轉的地址。

授權碼(authorization-code)方式
授權碼方式使用
所謂落地頁, 就是訪問授權后用戶回到的頁面.
如果你還沒開始開發(fā), 可以先用這個網站試一試, 本頁面會生成一個鏈接,點擊后會跳轉到授權頁面。
在例子中, 落地頁應該填: http://django-oauth-toolkit.herokuapp.com/consumer/exchange/
最后點保存, 就完成了B側的應用注冊.
顯然, 你需要記下來自己的Client id和Client secret.
用戶將看到一個這樣的頁面(可以通過django國際化進行漢化):

用戶點擊授權之后, 將會被重定向到你的落地頁, 并在url中攜帶code
在例子中, 應該在該頁面, 輸入你的Client id和授權url:
你的域名/oauth2/authorize
, 然后獲得重定向地址, 并跳轉到如下頁面
你的落地頁后端拿到code之后, 需要請求token, 也就是你的落地頁后端需要發(fā)一個POST請求:
fetch(new Request('你的域名/oauth2/token/',{
method:'POST',
headers: {'Cache-Control': 'no-cache',
'Content-Type':'application/x-www-form-urlencoded'},
body:{
'client_id':'3RGYcLX5nj9vMT0UbjxjXmYikNrOwEEH2uofF6gq',
'client_secret':'Wu0tcWSpPk3AqUVw1FFS7zWuibEOxELlCp8AtQDPfq2qo991eH8oIGluFSDStEO80ndzWV32e5szIpyNWM5auj8HFTFrzqqnmYo5pYzuI6fFcKdfj90blHgMYivAgWLp',
'code':'yiKoD7Ms1EvE2dgj5dP51MepkJPFty',
'redirect_uri':'http://django-oauth-toolkit.herokuapp.com/consumer/exchange/',
'grant_type':'authorization_code'
}
})).then((resp)=>{console.log(resp)})
這一步的目的是將明文傳輸?shù)腃ODE換成服務器之間傳遞的TOKEN, 你可以開發(fā)另一個落地頁2, 或者通過參數(shù)復用同一個落地頁, 為防混亂, 在本文檔中, 我們使用落地頁2描述上述POST請求中的${YOUR_CALLBACK_PAGE}
在例子中, 你需要60秒內手動發(fā)送上述POST請求, 但是在正式集成中, 應該由落地頁的后端自動發(fā)送, 按F12打開瀏覽器調試工具, 填上一個圖片中右邊的表單, token url是
你的域名/oauth2/token/點Submit, 就能看到你發(fā)出了上述POST請求.
上述POST將給你如下返回值:
{
"access_token": "aVvBRVFMWPYhZPczNlaWdPTyT5g8Fk",
"expires_in": 36000,
"token_type": "Bearer",
"scope": "read write"
}
憑上述access_token, 用戶可以訪問B中該用戶全部授權資源, 例如, 落地頁2應該訪問下面API, 獲取并展示用戶信息, 完成系統(tǒng)A的登錄:
跳過授權碼
該方式需要你完全信任對方,可避免彈窗出現(xiàn)。在Applications的model中將skip_authorization = True,可在admin的后臺操作。

獲取用戶信息接口
url: /api/v2/user/
method: GET
header:
{"Authorization": "Bearer QUgU1t5MvaRuuMtaGy8gTCm3dtdGGL"}
Response
{
"email": "dfsdfzza@phytium.com.cn",
"password": "123",
"last_login": null,
"username": "fgfdsaasd",
"last_name": "發(fā)給對方",
"date_joined": "2020-07-23T02:12:34.588741"
}
后端代碼
這樣就能返回用戶自己的信息了。
class UsersSerializer(serializers.ModelSerializer):
class Meta:
model = Users
fields = '__all__'
depth = 1
class UserDetail(generics.GenericAPIView):
authentication_classes = [OAuth2Authentication]
def get(self, req, *args, **kwargs):
user = req.user.users
serializer = UsersSerializer(instance=user)
data = serializer.data
data['user'].pop('password')
return Response(serializer.data)



浙公網安備 33010602011771號