【DRF】使用 rest_auth 設(shè)置 DRF 的 API(數(shù)據(jù)庫(kù)/model) 訪問權(quán)限

轉(zhuǎn)自:https://blog.csdn.net/qq_29757283/article/details/86539882

本文配置部分主要參考 django-rest-auth 官方文檔 ?
另外添加了一些不同的使用方式:
({HTTPie,Curl}×{key,cookie}{\text{HTTPie}, \text{Curl}} \times {\text{key}, \text{cookie}}{HTTPie,Curl}×{key,cookie})

token(key) cookie
獲取值 3.2.1 3.3.1
HTTPie 3.2.2.2 3.3.2.1
Curl 3.2.2.1 3.3.2.2

Overview

  1. Configuration
    1.1 django-rest-auth
    1.2 django-rest-framework

  2. 驗(yàn)證
    2.1 It Works
    3 使用 rest_auth 獲取認(rèn)證倾剿,訪問
    3.1 了解 rest_auth 如何獲取認(rèn)證
    3.2 使用認(rèn)證的 token 訪問數(shù)據(jù)
    3.2.1 獲取 token(key) value
    3.2.1.1 curl 工具
    3.2.1.2 HTTPie
    3.2.2 使用賬號(hào)的 token 訪問 model(REST API)
    3.2.2.1 curl
    3.2.2.2 HTTPie
    3.2.2.3 POSTman 軟件
    3.2.2.4 基于 requests 庫(kù)的 Python 代碼
    3.3 使用登錄后 Set 的 Cookie 訪問數(shù)據(jù)
    3.3.1 登錄和 Set-Cookie
    3.3.2 使用 Cookie 訪問數(shù)據(jù)
    3.3.2.1 HTTPie
    3.3.2.2 Curl
    延伸
    Reference

  3. Configuration

1.1 django-rest-auth
因?yàn)?rest-auth 庫(kù)基于 DRF1聋袋,所以首先要安裝 DRF 我就不多說(shuō)了

pip install dango-rest-auth

<proj>/api/urls.py

嚴(yán)謹(jǐn)來(lái)說(shuō),哪個(gè) urls.py 文件取決于您如何設(shè)計(jì)項(xiàng)目源碼結(jié)構(gòu)纫塌,以及這個(gè)項(xiàng)目結(jié)構(gòu)如何對(duì)應(yīng) rest api苛萎。所以實(shí)際上每個(gè)人自己修改的 urls.py 未必相同桨昙。
(可以直接修改和 settings.py 同一路徑下的 urls.py,代碼和下面一樣腌歉,這樣就可以像下文一樣訪問 http://<domain>:[port]/api/rest_auth/login/ 了)

urlpatterns += [
path('api/rest_auth/', include('rest_auth.urls')),
]
1
2
3
<proj>/<proj>/settings.py :

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',

#
# install
#
'rest_framework',
'rest_framework.authtoken',

'rest_auth',

[...]

]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

1.2 django-rest-framework
<proj>/<proj>/settings.py

[...]

REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}

[...]
1
2
3
4
5
6
7
8
9
10
11
12
13
直接添加上面段落蛙酪。
這一段非常重要,如果沒有這一段的化翘盖,那么可能使用正確的認(rèn)證方式(比如下面用到的 user’s key in tokens)也無(wú)法訪問成功桂塞。

  1. 驗(yàn)證

2.1 It Works

現(xiàn)在直接通過(guò) DRF 提供的 rest api 訪問 model 將會(huì)失敗(要求權(quán)限認(rèn)證)馍驯。

3 使用 rest_auth 獲取認(rèn)證阁危,訪問
3.1 了解 rest_auth 如何獲取認(rèn)證
post manage.py createsuperuser 的賬號(hào)密碼到 django-rest-auth 的 end-point(即 API),獲得到 token(rest_auth 使用“key” 表示):

POST 正確的賬號(hào)密碼之后汰瘫,現(xiàn)在就可以繼續(xù)使用瀏覽器訪問其它編寫的 endpoint(REST API)狂打,比如 DRF 官方實(shí)現(xiàn)了一個(gè) Snippet model 用作 Tutorial,瀏覽器在 rest_auth 登錄之后吟吝,就可以訪問 http://<domain>:[port]/api/snippet/菱父。

(這是因?yàn)闉g覽器已經(jīng) Set-Cookie 過(guò)了,下文會(huì)講到。)

3.2 使用認(rèn)證的 token 訪問數(shù)據(jù)
3.2.1 獲取 token(key) value
token 意思是 user’s key 的集合官辽。在 Django 的 admin 后臺(tái)管理中可以看到:

通過(guò)瀏覽器訪問 rest_auth 的 rest api 獲取 token 的方式我們已經(jīng)在 3.1 節(jié)看過(guò)了。
當(dāng)然粟瞬,實(shí)際上我們不會(huì)通過(guò)瀏覽器直接訪問 http://...:.../api/rest_auth/login/ 這種方式來(lái)獲取 token同仆。

在前端中使用 javascript,在應(yīng)用程序中裙品,即是使用編程語(yǔ)言的網(wǎng)絡(luò)庫(kù)俗批。
它們?cè)趨?shù)上大同小異,在測(cè)試(感受如何使用)的時(shí)候市怎,還是先通過(guò)命令行工具來(lái)訪問 ?

3.2.1.1 curl 工具
curl -X POST \ -H "Content-Type: application/json" \ --data '{"username": "<your username>", "password": "<your password>"}' \ "http://localhost:8000/api/rest_auth/login/" {"key":"b20...380"}
1 2 3 4 5 6 3.2.1.2 HTTPie http POST
"http://localhost:8000/api/rest_auth/login/"
username=<your username> password=<your password>
HTTP/1.1 200 OK
Allow: POST, OPTIONS
Content-Length: 50
Content-Type: application/json
Date: Mon, 29 Jul 2019 04:25:42 GMT
Server: WSGIServer/0.2 CPython/3.6.8
Set-Cookie: csrftoken=RRkTbmUuv6kWZtbPnJ0Yx23SIXRRe2qZV8z8ycHE2ORpU9McplBLIpmcGOLQDMcy; expires=Mon, 27 Jul 2020 04:25:42 GMT; Max-Age=31449600; Path=/; SameSite=Lax
Set-Cookie: sessionid=m65g5ansi11jhgncmlqiaroemjgplyy8; expires=Mon, 12 Aug 2019 04:25:42 GMT; HttpOnly; Max-Age=1209600; Path=/; SameSite=Lax
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN

{
"key": "b20...380"
}

$
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
3.2.2 使用賬號(hào)的 token 訪問 model(REST API)
3.2.2.1 curl

即:

$ curl -X GET <url> -H 'Authorization: Token <上文POST之后獲得的key值>'
1
3.2.2.2 HTTPie
HTTPie 使用 token GET 數(shù)據(jù):

$ http GET
"http://localhost:8000/api/snippet/"
"Authorization: Token b20...380"
HTTP/1.1 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 696
Content-Type: application/json
Date: Mon, 29 Jul 2019 04:35:30 GMT
Server: WSGIServer/0.2 CPython/3.6.8
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN

[
{
"code": "print('hello world')",
"id": 1,
"language": "python",
"linenos": false,
"style": "friendly",
"title": "Hello World of Python"
}
]

$
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
HTTPie 使用 token POST 數(shù)據(jù):

$ http POST
"http://localhost:8000/api/snippet/"
'Authorization: Token b20...380'
title='Hello World of C'
code="#include <stdio.h>\n\nint main(){\n printf("hello world\n");\n}"
language=c

HTTP/1.1 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 168
Content-Type: application/json
Date: Tue, 30 Jul 2019 01:43:36 GMT
Server: WSGIServer/0.2 CPython/3.6.8
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN

{
"code": "#include <stdio.h>\n\nint main(){\n printf("hello world\n");\n}"
"id": 3,
"language": "c",
"linenos": false,
"style": "friendly",
"title": "Hello World of C"
}

$
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
DELETE 數(shù)據(jù)同理岁忘,只需要將 ‘GET’ 換成 ‘DELETE’, 同時(shí)根據(jù)原本定義好的 REST API区匠,需要將 url 具體到 <int:pk> 即可(.../api/sinppet/1/)

3.2.2.3 POSTman 軟件

注意格式: Authorization : Token <the value>;
token 和 value 中間有空格

3.2.2.4 基于 requests 庫(kù)的 Python 代碼
上面分別演示了使用 curl, httpie 命令行工具和 POSTman 桌面 GUI 工具通過(guò) token 訪問 rest api干像。
現(xiàn)在落實(shí)到代碼中 ?

獲取 token:

import json
import requests

r = requests.post("http://<domain>:<port>/api/rest_auth/login/",
data={'username': '<username>', 'password': '<password>'})
if r.status_code == 200:
token = json.loads(r.text)['key']
else:
raise RuntimeError(r.text)

1
2
3
4
5
6
7
8
9
10
使用 token 訪問數(shù)據(jù):

r = requests.get('http://<domain>:<port>/api/snippet/',
headers={'Authorization': 'Token {}'.format(token)})
if r.status_code == 200:
print(json.loads(r.text))
else:
raise RuntimeError(r.text)

1
2
3
4
5
6
7

3.3 使用登錄后 Set 的 Cookie 訪問數(shù)據(jù)
3.3.1 登錄和 Set-Cookie
由于沒有單獨(dú)實(shí)現(xiàn) login 功能的頁(yè)面。所以這里也就直接借用 rest_auth 模塊的 login endpoint驰弄。
和前文一樣麻汰,使用 HTTPie 登錄等到的 HTTP Response 如下:

$ http POST
"http://localhost:8000/api/rest_auth/login/"
username=<your username> password=<your password>
HTTP/1.1 200 OK
Allow: POST, OPTIONS
Content-Length: 50
Content-Type: application/json
Date: Mon, 29 Jul 2019 04:25:42 GMT
Server: WSGIServer/0.2 CPython/3.6.8
Set-Cookie: csrftoken=RRk...Mcy; expires=Mon, 27 Jul 2020 04:25:42 GMT; Max-Age=31449600; Path=/; SameSite=Lax
Set-Cookie: sessionid=m65g5ansi11jhgncmlqiaroemjgplyy8; expires=Mon, 12 Aug 2019 04:25:42 GMT; HttpOnly; Max-Age=1209600; Path=/; SameSite=Lax
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN

{
"key": "b20...380"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
由上面結(jié)果顯然可以看出,服務(wù)器響應(yīng)了 Set-Cookie 內(nèi)容戚篙。
如果是瀏覽器的化五鲫,就會(huì)解析這個(gè) Set-Cookie 內(nèi)容,然后對(duì)于瀏覽器來(lái)說(shuō)岔擂,它就知道了和該網(wǎng)站訪問交互有了一個(gè)狀態(tài)(“登錄過(guò)”)位喂,這個(gè)狀態(tài)就是通過(guò) Cookie 內(nèi)容體現(xiàn)。也就是說(shuō)智亮,之后在瀏覽器上訪問這個(gè)網(wǎng)站的時(shí)候忆某,瀏覽器都會(huì)自動(dòng)帶上 Cookie 發(fā)送出去請(qǐng)求点待。

因?yàn)槭堑卿涍^(guò)阔蛉,也就是說(shuō)認(rèn)證過(guò)了,所以訪問數(shù)據(jù)是可以被允許的癞埠。也就是說(shuō)通過(guò) cookie 來(lái)表明自己的這個(gè)請(qǐng)求是認(rèn)證過(guò)的請(qǐng)求 - 即有了 cookie 就不需要 token状原。

那么顯然,直接 GET 某個(gè) REST API 是不含有 Cookie 的苗踪;所以這里要根據(jù)登錄后獲得 Response 中的 Set-Cookie 來(lái)手動(dòng)發(fā)送帶有 Cookie 的請(qǐng)求颠区。
以上面實(shí)例中的 Set-Cookie 內(nèi)容為例,不同的命令行工具的 Cookie 使用方式如下?

3.3.2 使用 Cookie 訪問數(shù)據(jù)
注意上面的 HTTP Response 中有兩個(gè) Set-Cookie 對(duì)應(yīng)著兩個(gè)核心的內(nèi)容:一個(gè)是 csrftoken通铲,一個(gè)是 sessionid毕莱。

csrftoken
在提交表單時(shí)使用(創(chuàng)建、修改、更新和刪除)朋截,這是為了防止跨域訪問蛹稍。
sessionid
翻譯過(guò)來(lái)就時(shí)“會(huì)話 ID”,所以服務(wù)器判斷當(dāng)前請(qǐng)求對(duì)應(yīng)的用戶部服,和這個(gè)用戶是否登錄過(guò)依賴的就是這個(gè) cookie 值唆姐。
如果只是 GET 數(shù)據(jù),那么 cookie 中只需要這個(gè)內(nèi)容即可廓八,不過(guò)為了簡(jiǎn)單起見奉芦,還是全部都一塊帶上好了。
3.3.2.1 HTTPie
$ http GET
"http://localhost:8000/api/snippet/"
'Cookie: csrftoken=RRk...Mcy;sessionid=m65g5ansi11jhgncmlqiaroemjgplyy8'
HTTP/1.1 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 696
Content-Type: application/json
Date: Mon, 29 Jul 2019 04:25:34 GMT
Server: WSGIServer/0.2 CPython/3.6.8
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN

[
{
"code": "print('hello world')",
"id": 1,
"language": "python",
"linenos": false,
"style": "friendly",
"title": "Hello World of Python"
}
]

$
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
在 HTTPie 文檔 ? 中對(duì)于 Cookie 的使用有著不錯(cuò)的描述:

Cookies
HTTP clients send cookies to the server as regular HTTP headers. That means, HTTPie does not offer any special syntax for specifying cookies — the usual Header:Value notation is used:

Send a single cookie:
$ http example.org Cookie:sessionid=foo

GET / HTTP/1.1
Accept: /
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cookie: sessionid=foo
Host: example.org
User-Agent: HTTPie/0.9.9
1
2
3
4
5
6
7
Send multiple cookies (note the header is quoted to prevent the shell from interpreting the ;):
$ http example.org 'Cookie:sessionid=foo;another-cookie=bar'

GET / HTTP/1.1
Accept: /
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cookie: sessionid=foo;another-cookie=bar
Host: example.org
User-Agent: HTTPie/0.9.9
1
2
3
4
5
6
7
If you often deal with cookies in your requests, then chances are you’d appreciate the sessions feature.

3.3.2.2 Curl
curl -X GET
-b 'csrftoken=RRk...Mcy;sessionid=datfyeyowug9hktb3l81ilwychlw58v3'
"http://localhost:8000/api/snippet/"
[{"id":1,"title":"Hello World of Python","code":"print('hello world')","linenos":false,"language":"python","style":"friendly"}]
1
2
3
4
5
使用 -b 或 --cookie 指定 Cookie(來(lái)源可以是文件或字符串)剧蹂,使用 ; 分隔/連接多個(gè) cookie声功。

當(dāng)然,使用 Curl 格式顯然沒有 HTTPie 美觀宠叼。不過(guò) Curl 仍然是一個(gè)值得了解的命令行工具减噪。

延伸
使用 rest_auth 相當(dāng)了簡(jiǎn)化了我們手動(dòng)去編寫代碼實(shí)現(xiàn) token 驗(yàn)證的相關(guān)邏輯。
但是如果想要從代碼層面詳細(xì)了解 token车吹,或者說(shuō)自己實(shí)現(xiàn)一份和 rest_auth 相近功能的東西筹裕,這里有幾篇重要的參考文章:

How to Implement Token Authentication using Django REST Framework ?
Django REST framework 的TokenAuth認(rèn)證及外鍵Serializer基本實(shí)現(xiàn) ?
Django REST Framework Doc – 認(rèn)證 ?

Reference
The Ultimate Tutorial for Django REST Framework: Login and Authentication (Part 2) ?

django rest auth Doc > Installation ?
————————————————
版權(quán)聲明:本文為CSDN博主「RDpWTeHM」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議窄驹,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明朝卒。
原文鏈接:https://blog.csdn.net/qq_29757283/article/details/86539882

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市乐埠,隨后出現(xiàn)的幾起案子抗斤,更是在濱河造成了極大的恐慌,老刑警劉巖丈咐,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瑞眼,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡棵逊,警方通過(guò)查閱死者的電腦和手機(jī)伤疙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)辆影,“玉大人徒像,你說(shuō)我怎么就攤上這事⊥芗ィ” “怎么了锯蛀?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)次慢。 經(jīng)常有香客問我旁涤,道長(zhǎng)翔曲,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任劈愚,我火速辦了婚禮部默,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘造虎。我一直安慰自己傅蹂,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布算凿。 她就那樣靜靜地躺著份蝴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪氓轰。 梳的紋絲不亂的頭發(fā)上婚夫,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音署鸡,去河邊找鬼案糙。 笑死,一個(gè)胖子當(dāng)著我的面吹牛靴庆,可吹牛的內(nèi)容都是我干的时捌。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼炉抒,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼奢讨!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起焰薄,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤拿诸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后塞茅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體亩码,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年野瘦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了描沟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡缅刽,死狀恐怖啊掏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情衰猛,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布刹孔,位于F島的核電站啡省,受9級(jí)特大地震影響娜睛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜卦睹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一畦戒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧结序,春花似錦障斋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至返敬,卻和暖如春遂庄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背劲赠。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工涛目, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人凛澎。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓霹肝,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親塑煎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子阿迈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容