Hướng dẫn python requests session auth - python yêu cầu xác thực phiên

Tôi đang cố gắng sử dụng xác thực HTTP cơ bản trong Python. Tôi đang sử dụng thư viện yêu cầu:

Show

Nội phân chính

  • 1. Tên người dùng & mật khẩu dưới dạng thông tin đăng nhập:
  • 2. Mã thông báo cơ bản là thông tin đăng nhập:
  • Cách xác định xác thực
  • Đặt sơ đồ xác thực
  • Apache mod_wsgi Cấu hình cụ thể
  • Tham khảo API
  • BASICAUMPENTION
  • Tokenenuthentication
  • Tạo mã thông báo
  • SessionAuthentication
  • Điều khiển từ xa
  • Xác thực tùy chỉnh
  • Gói của bên thứ ba
  • django-rest-knox
  • Cài đặt & Cấu hình
  • Django Rest Framework Oauth
  • Cài đặt & Cấu hình
  • Django Rest Framework Oauth
  • Xác thực mã thông báo web JSON
  • Hawk HTTP Xác thực
  • Xác thực chữ ký HTTP
  • django-rest-auth / dj-rest-auth
  • django-rest-authemail
  • Django-Rest-Durin

auth = requests.post('http://' + hostname, auth=HTTPBasicAuth(user, password))
request = requests.get('http://' + hostname + '/rest/applications')

drfpasswordlessauth variable:

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})

Biến biểu mẫu phản hồi Biến Auth:

<[]>
401
CaseInsensitiveDict({'content-length': '1073', 'x-powered-by': 'Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.2.2 Java/Oracle Corporation/1.7)', 'expires': 'Thu, 01 Jan 1970 00:00:00 UTC', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'No-cache', 'cache-control': 'no-cache', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html', 'www-authenticate': 'Basic realm="controller_realm"'})

Nhưng khi tôi cố gắng lấy dữ liệu từ các vị trí khác nhau, - Tôi đã gặp lỗi 401

Theo tôi hiểu - trong yêu cầu thứ hai không phải là tham số phiên thay thế.

  • Basic Auth là một trong nhiều kỹ thuật ủy quyền HTTP được sử dụng để xác nhận quyền truy cập vào điểm cuối HTTP. Hiểu về cơ bản là rất đơn giản, người dùng yêu cầu quyền truy cập vào điểm cuối cũng phải cung cấp,
  • Tên người dùng và mật khẩu dưới dạng thông tin đăng nhập trong cuộc gọi API (hoặc)

Mã thông báo ủy quyền cơ bản làm thông tin đăng nhập trong tiêu đề yêu cầu

https://postman-echo.com/basic-auth

Chúng ta hãy khám phá cả hai cách trong Python. Với mục đích của bản demo, chúng tôi sẽ sử dụng điểm cuối cơ bản được phơi bày bởi Postman

1. Tên người dùng & mật khẩu dưới dạng thông tin đăng nhập:

Mặc dù đây là một yêu cầu GET, các cuộc gọi Auth Basic cho tất cả các phương thức HTTP khác sẽ vẫn giữ nguyên với một ngoại lệ mà thay vì phương thức Get (), hãy sử dụng phương thức điều trị được hiển thị bởi Thư viện Yêu cầu.

import requests

url = "https://postman-echo.com/basic-auth"
username = "postman"
password = "password"

response = requests.get(url, auth=(username, password))
print(response.status_code)
print(response.json())

2. Mã thông báo cơ bản là thông tin đăng nhập:

Chúng tôi có thể trực tiếp nhúng tên người dùng và mật khẩu cơ bản vào yêu cầu bằng cách truyền tên người dùng và mật khẩu dưới dạng phương thức

https://postman-echo.com/basic-auth
3 và phương thức get () trong các yêu cầu sẽ đảm nhận ủy quyền cơ bản cho chúng tôi.

Basic cG9zdG1hbjpwYXNzd29yZA==
import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())

Có một cơ hội là đối với API, bạn chỉ nhận được mã thông báo Auth cơ bản thay vì tên người dùng và mật khẩu. Trong kịch bản này, tất cả những gì bạn cần làm là nhúng mã thông báo auth cơ bản làm tiêu đề ủy quyền trong khi thực hiện cuộc gọi API. Một mã thông báo authic cơ bản mẫu sẽ trông như thế này

Đầu ra

200
{'authenticated': True}

Đối với các yêu cầu được thực hiện với thông tin xác thực cơ bản hợp lệ

401
{'authenticated': False}

authentication.py

Đối với các yêu cầu được thực hiện với thông tin xác thực cơ bản không hợp lệ

Auth cần phải có thể cắm được.

-Jacob Kaplan-Moss, "Thực hành tồi tệ nhất"

Xác thực là cơ chế liên kết một yêu cầu đến với một tập hợp các thông tin xác định, chẳng hạn như người dùng yêu cầu đến từ hoặc mã thông báo mà nó đã ký. Các chính sách cho phép và điều chỉnh sau đó có thể sử dụng các thông tin đó để xác định xem yêu cầu có nên được phép hay không.

REST Framework cung cấp một số sơ đồ xác thực ra khỏi hộp và cũng cho phép bạn thực hiện các chương trình tùy chỉnh.

Xác thực luôn chạy ngay khi bắt đầu xem, trước khi kiểm tra cho phép và điều chỉnh, và trước khi bất kỳ mã nào khác được phép tiến hành.

Thuộc tính

https://postman-echo.com/basic-auth
4 thường sẽ được đặt thành một thể hiện của lớp
https://postman-echo.com/basic-auth
6 của gói
https://postman-echo.com/basic-auth
5.


Thuộc tính

https://postman-echo.com/basic-auth
7 được sử dụng cho bất kỳ thông tin xác thực bổ sung nào, ví dụ, nó có thể được sử dụng để biểu thị mã thông báo xác thực mà yêu cầu đã được ký kết. Don't forget that authentication by itself won't allow or disallow an incoming request, it simply identifies the credentials that the request was made with.

Lưu ý: Đừng quên rằng xác thực của chính nó sẽ không cho phép hoặc không cho phép yêu cầu đến, nó chỉ cần xác định thông tin đăng nhập mà yêu cầu được thực hiện.


Cách xác định xác thực

Để biết thông tin về cách thiết lập các chính sách quyền cho API của bạn, vui lòng xem tài liệu quyền.

Các sơ đồ xác thực luôn được định nghĩa là danh sách các lớp. REST Framework sẽ cố gắng xác thực với mỗi lớp trong danh sách và sẽ đặt

https://postman-echo.com/basic-auth
4 và
https://postman-echo.com/basic-auth
7 bằng cách sử dụng giá trị trả về của lớp đầu tiên xác thực thành công.

Nếu không có lớp xác thực,

https://postman-echo.com/basic-auth
4 sẽ được đặt thành một thể hiện là
import requests

url = "https://postman-echo.com/basic-auth"
username = "postman"
password = "password"

response = requests.get(url, auth=(username, password))
print(response.status_code)
print(response.json())
1 và
https://postman-echo.com/basic-auth
7 sẽ được đặt thành
import requests

url = "https://postman-echo.com/basic-auth"
username = "postman"
password = "password"

response = requests.get(url, auth=(username, password))
print(response.status_code)
print(response.json())
3.

Đặt sơ đồ xác thực

Apache mod_wsgi Cấu hình cụ thể

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ]
}

Tham khảo API

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
0

BASICAUMPENTION

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
1

Tokenenuthentication

  • HTTP 401 trái phép
  • HTTP 403 bị từ chối

Các phản hồi của HTTP 401 phải luôn bao gồm một tiêu đề

Basic cG9zdG1hbjpwYXNzd29yZA==
1, hướng dẫn khách hàng cách xác thực. Phản hồi của HTTP 403 không bao gồm tiêu đề
Basic cG9zdG1hbjpwYXNzd29yZA==
1.

Loại phản hồi sẽ được sử dụng phụ thuộc vào sơ đồ xác thực. Mặc dù nhiều sơ đồ xác thực có thể được sử dụng, nhưng chỉ có một sơ đồ có thể được sử dụng để xác định loại phản hồi. Lớp xác thực đầu tiên được đặt trên chế độ xem được sử dụng khi xác định loại phản hồi.The first authentication class set on the view is used when determining the type of response.

Lưu ý rằng khi một yêu cầu có thể xác thực thành công, nhưng vẫn bị từ chối cho phép thực hiện yêu cầu, trong trường hợp đó, phản hồi

Basic cG9zdG1hbjpwYXNzd29yZA==
3 sẽ luôn được sử dụng, bất kể sơ đồ xác thực.

Apache mod_wsgi Cấu hình cụ thể

Lưu ý rằng nếu triển khai cho Apache bằng MOD_WSGI, tiêu đề ủy quyền không được chuyển qua ứng dụng WSGI theo mặc định, vì giả định rằng xác thực sẽ được Apache xử lý, thay vì ở cấp ứng dụng.

Nếu bạn đang triển khai cho Apache và sử dụng bất kỳ xác thực không dựa trên phiên nào, bạn sẽ cần cấu hình rõ ràng MOD_WSGI để chuyển các tiêu đề cần thiết qua ứng dụng. Điều này có thể được thực hiện bằng cách chỉ định Chỉ thị

Basic cG9zdG1hbjpwYXNzd29yZA==
4 trong bối cảnh thích hợp và đặt nó thành
Basic cG9zdG1hbjpwYXNzd29yZA==
5.

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
2

Tham khảo API

BASICAUMPENTION

Sơ đồ xác thực này sử dụng xác thực cơ bản HTTP, được ký vào tên người dùng và mật khẩu của người dùng. Xác thực cơ bản thường chỉ phù hợp để kiểm tra.

Nếu được xác thực thành công,

Basic cG9zdG1hbjpwYXNzd29yZA==
6 cung cấp các thông tin sau đây.

  • https://postman-echo.com/basic-auth
    
    4 sẽ là một ví dụ Django
    https://postman-echo.com/basic-auth
    
    6.
  • https://postman-echo.com/basic-auth
    
    7 sẽ là
    import requests
    
    url = "https://postman-echo.com/basic-auth"
    username = "postman"
    password = "password"
    
    response = requests.get(url, auth=(username, password))
    print(response.status_code)
    print(response.json())
    
    3.

Các phản hồi không xác thực bị từ chối cho phép sẽ dẫn đến phản hồi

import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
1 với tiêu đề xác thực www thích hợp. Ví dụ:

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
3

Lưu ý: Nếu bạn sử dụng

Basic cG9zdG1hbjpwYXNzd29yZA==
6 trong sản xuất, bạn phải đảm bảo rằng API của bạn chỉ khả dụng trên
import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
3. Bạn cũng nên đảm bảo rằng các máy khách API của bạn sẽ luôn yêu cầu lại tên người dùng và mật khẩu khi đăng nhập và sẽ không bao giờ lưu trữ các chi tiết đó để lưu trữ liên tục.
If you use
Basic cG9zdG1hbjpwYXNzd29yZA==
6 in production you must ensure that your API is only available over
import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
3. You should also ensure that your API clients will always re-request the username and password at login, and will never store those details to persistent storage.

Tokenenuthentication


Lưu ý: Xác thực mã thông báo được cung cấp bởi Django Rest Framework là một triển khai khá đơn giản. The token authentication provided by Django REST framework is a fairly simple implementation.

Đối với việc triển khai cho phép nhiều hơn một mã thông báo cho mỗi người dùng, có một số chi tiết triển khai bảo mật chặt chẽ hơn và hỗ trợ hết hạn mã thông báo, vui lòng xem gói bên thứ ba Django REST KNOX.


Sơ đồ xác thực này sử dụng sơ đồ xác thực HTTP dựa trên mã thông báo đơn giản. Xác thực mã thông báo phù hợp cho các thiết lập máy khách-máy chủ, chẳng hạn như máy tính để bàn gốc và máy khách di động.

Để sử dụng sơ đồ

import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
4, bạn sẽ cần định cấu hình các lớp xác thực để bao gồm
import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
4 và bao gồm cả
import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
6 trong cài đặt
import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
7 của bạn:

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
4

Đảm bảo chạy

import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
8 sau khi thay đổi cài đặt của bạn.

Ứng dụng

import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
6 cung cấp di chuyển cơ sở dữ liệu Django.

Bạn cũng sẽ cần tạo mã thông báo cho người dùng của mình.

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
5

Để khách hàng xác thực, khóa mã thông báo nên được bao gồm trong tiêu đề

200
{'authenticated': True}
0 HTTP. Phím phải được đặt trước bằng chuỗi "mã thông báo" theo nghĩa đen, với khoảng trắng ngăn cách hai chuỗi. Ví dụ:

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
6

Nếu bạn muốn sử dụng một từ khóa khác trong tiêu đề, chẳng hạn như

200
{'authenticated': True}
1, chỉ cần phân lớp con
import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
4 và đặt biến lớp
200
{'authenticated': True}
3.

Nếu được xác thực thành công,

import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
4 cung cấp các thông tin sau đây.

  • https://postman-echo.com/basic-auth
    
    4 sẽ là một ví dụ Django
    https://postman-echo.com/basic-auth
    
    6.
  • https://postman-echo.com/basic-auth
    
    7 sẽ là
    import requests
    
    url = "https://postman-echo.com/basic-auth"
    username = "postman"
    password = "password"
    
    response = requests.get(url, auth=(username, password))
    print(response.status_code)
    print(response.json())
    
    3.

Các phản hồi không xác thực bị từ chối cho phép sẽ dẫn đến phản hồi

import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
1 với tiêu đề xác thực www thích hợp. Ví dụ:

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
7

Lưu ý: Nếu bạn sử dụng

Basic cG9zdG1hbjpwYXNzd29yZA==
6 trong sản xuất, bạn phải đảm bảo rằng API của bạn chỉ khả dụng trên
import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
3. Bạn cũng nên đảm bảo rằng các máy khách API của bạn sẽ luôn yêu cầu lại tên người dùng và mật khẩu khi đăng nhập và sẽ không bao giờ lưu trữ các chi tiết đó để lưu trữ liên tục.

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
8

Tokenenuthentication If you use

import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
4 in production you must ensure that your API is only available over
import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
3.


Lưu ý: Xác thực mã thông báo được cung cấp bởi Django Rest Framework là một triển khai khá đơn giản.

Đối với việc triển khai cho phép nhiều hơn một mã thông báo cho mỗi người dùng, có một số chi tiết triển khai bảo mật chặt chẽ hơn và hỗ trợ hết hạn mã thông báo, vui lòng xem gói bên thứ ba Django REST KNOX.

Sơ đồ xác thực này sử dụng sơ đồ xác thực HTTP dựa trên mã thông báo đơn giản. Xác thực mã thông báo phù hợp cho các thiết lập máy khách-máy chủ, chẳng hạn như máy tính để bàn gốc và máy khách di động.

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
9

Để sử dụng sơ đồ

import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
4, bạn sẽ cần định cấu hình các lớp xác thực để bao gồm
import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
4 và bao gồm cả
import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
6 trong cài đặt
import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
7 của bạn:

Đảm bảo chạy

import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
8 sau khi thay đổi cài đặt của bạn.

<[]>
401
CaseInsensitiveDict({'content-length': '1073', 'x-powered-by': 'Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.2.2 Java/Oracle Corporation/1.7)', 'expires': 'Thu, 01 Jan 1970 00:00:00 UTC', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'No-cache', 'cache-control': 'no-cache', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html', 'www-authenticate': 'Basic realm="controller_realm"'})
0

Ứng dụng
import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
6 cung cấp di chuyển cơ sở dữ liệu Django.

Bạn cũng sẽ cần tạo mã thông báo cho người dùng của mình.

<[]>
401
CaseInsensitiveDict({'content-length': '1073', 'x-powered-by': 'Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.2.2 Java/Oracle Corporation/1.7)', 'expires': 'Thu, 01 Jan 1970 00:00:00 UTC', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'No-cache', 'cache-control': 'no-cache', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html', 'www-authenticate': 'Basic realm="controller_realm"'})
1

Lưu ý rằng phần URL của mẫu có thể là bất cứ điều gì bạn muốn sử dụng.

Chế độ xem

401
{'authenticated': False}
6 sẽ trả về phản hồi JSON khi các trường
401
{'authenticated': False}
8 và
401
{'authenticated': False}
9 hợp lệ được đăng lên chế độ xem bằng dữ liệu biểu mẫu hoặc JSON:

<[]>
401
CaseInsensitiveDict({'content-length': '1073', 'x-powered-by': 'Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.2.2 Java/Oracle Corporation/1.7)', 'expires': 'Thu, 01 Jan 1970 00:00:00 UTC', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'No-cache', 'cache-control': 'no-cache', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html', 'www-authenticate': 'Basic realm="controller_realm"'})
2

Lưu ý rằng chế độ xem

401
{'authenticated': False}
6 mặc định sử dụng rõ ràng các yêu cầu và phản hồi của JSON, thay vì sử dụng các lớp trình kết xuất và trình phân tích cú pháp mặc định trong cài đặt của bạn.

Theo mặc định, không có quyền hoặc điều chỉnh được áp dụng cho chế độ xem

401
{'authenticated': False}
6. Nếu bạn muốn áp dụng cho bướm ga, bạn sẽ cần ghi đè lớp xem và bao gồm chúng bằng thuộc tính
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ]
}
2.

Nếu bạn cần một phiên bản tùy chỉnh của chế độ xem

401
{'authenticated': False}
6, bạn có thể làm như vậy bằng cách phân lớp lớp xem
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ]
}
4 và sử dụng nó trong URL Conf của bạn.

Ví dụ: bạn có thể trả về thông tin người dùng bổ sung ngoài giá trị

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ]
}
5:

<[]>
401
CaseInsensitiveDict({'content-length': '1073', 'x-powered-by': 'Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.2.2 Java/Oracle Corporation/1.7)', 'expires': 'Thu, 01 Jan 1970 00:00:00 UTC', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'No-cache', 'cache-control': 'no-cache', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html', 'www-authenticate': 'Basic realm="controller_realm"'})
3

Và trong

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ]
}
6 của bạn:

<[]>
401
CaseInsensitiveDict({'content-length': '1073', 'x-powered-by': 'Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.2.2 Java/Oracle Corporation/1.7)', 'expires': 'Thu, 01 Jan 1970 00:00:00 UTC', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'No-cache', 'cache-control': 'no-cache', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html', 'www-authenticate': 'Basic realm="controller_realm"'})
4

Với quản trị viên Django

Cũng có thể tạo mã thông báo bằng tay thông qua giao diện quản trị. Trong trường hợp bạn đang sử dụng một cơ sở người dùng lớn, chúng tôi khuyên bạn nên vá lớp

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ]
}
7 tùy chỉnh nó theo nhu cầu của bạn, cụ thể hơn bằng cách khai báo trường
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ]
}
8 là
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ]
}
9.

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
00:

<[]>
401
CaseInsensitiveDict({'content-length': '1073', 'x-powered-by': 'Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.2.2 Java/Oracle Corporation/1.7)', 'expires': 'Thu, 01 Jan 1970 00:00:00 UTC', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'No-cache', 'cache-control': 'no-cache', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html', 'www-authenticate': 'Basic realm="controller_realm"'})
5

Sử dụng lệnh Django Management.py

Vì phiên bản 3.6.4, có thể tạo mã thông báo người dùng bằng lệnh sau:

<[]>
401
CaseInsensitiveDict({'content-length': '1073', 'x-powered-by': 'Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.2.2 Java/Oracle Corporation/1.7)', 'expires': 'Thu, 01 Jan 1970 00:00:00 UTC', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'No-cache', 'cache-control': 'no-cache', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html', 'www-authenticate': 'Basic realm="controller_realm"'})
6

Lệnh này sẽ trả về mã thông báo API cho người dùng đã cho, tạo nó nếu nó không tồn tại:

<[]>
401
CaseInsensitiveDict({'content-length': '1073', 'x-powered-by': 'Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.2.2 Java/Oracle Corporation/1.7)', 'expires': 'Thu, 01 Jan 1970 00:00:00 UTC', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'No-cache', 'cache-control': 'no-cache', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html', 'www-authenticate': 'Basic realm="controller_realm"'})
7

Trong trường hợp bạn muốn tái tạo mã thông báo (ví dụ: nếu nó đã bị xâm phạm hoặc bị rò rỉ), bạn có thể vượt qua một tham số bổ sung:

<[]>
401
CaseInsensitiveDict({'content-length': '1073', 'x-powered-by': 'Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.2.2 Java/Oracle Corporation/1.7)', 'expires': 'Thu, 01 Jan 1970 00:00:00 UTC', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'No-cache', 'cache-control': 'no-cache', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html', 'www-authenticate': 'Basic realm="controller_realm"'})
8

SessionAuthentication

Sơ đồ xác thực này sử dụng phụ trợ phiên mặc định của Django để xác thực. Xác thực phiên phù hợp với các máy khách AJAX đang chạy trong cùng bối cảnh phiên với trang web của bạn.

Nếu được xác thực thành công,

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
01 cung cấp các thông tin sau đây.

  • https://postman-echo.com/basic-auth
    
    4 sẽ là một ví dụ Django
    https://postman-echo.com/basic-auth
    
    6.
  • https://postman-echo.com/basic-auth
    
    7 sẽ là
    import requests
    
    url = "https://postman-echo.com/basic-auth"
    username = "postman"
    password = "password"
    
    response = requests.get(url, auth=(username, password))
    print(response.status_code)
    print(response.json())
    
    3.

Các phản hồi không xác thực bị từ chối cho phép sẽ dẫn đến phản hồi

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
06.

Nếu bạn đang sử dụng API kiểu AJAX với sessionAuthentication, bạn sẽ cần đảm bảo rằng bạn bao gồm mã thông báo CSRF hợp lệ cho bất kỳ cuộc gọi phương thức HTTP "không an toàn" nào, chẳng hạn như

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
07,
<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
08,
<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
09 hoặc
<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
10. Xem tài liệu Django CSRF để biết thêm chi tiết.

Cảnh báo: Luôn sử dụng chế độ xem đăng nhập tiêu chuẩn của Django khi tạo các trang đăng nhập. Điều này sẽ đảm bảo chế độ xem đăng nhập của bạn được bảo vệ đúng.: Always use Django's standard login view when creating login pages. This will ensure your login views are properly protected.

Xác thực CSRF trong Khung REST hoạt động hơi khác với DJANGO tiêu chuẩn do nhu cầu hỗ trợ cả xác thực phiên và không dựa trên phiên cho cùng một quan điểm. Điều này có nghĩa là chỉ các yêu cầu được xác thực mới yêu cầu mã thông báo CSRF và các yêu cầu ẩn danh mới có thể được gửi mà không cần mã thông báo CSRF. Hành vi này không phù hợp cho các chế độ xem đăng nhập, điều này phải luôn luôn áp dụng xác thực CSRF.

Điều khiển từ xa

Sơ đồ xác thực này cho phép bạn ủy quyền xác thực cho máy chủ web của mình, thiết lập biến môi trường

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
11.

Để sử dụng nó, bạn phải có

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
12 (hoặc một lớp con) trong cài đặt
<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
13 của bạn. Theo mặc định,
<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
14 tạo các đối tượng
https://postman-echo.com/basic-auth
6 cho các tên người dùng chưa tồn tại. Để thay đổi điều này và hành vi khác, hãy tham khảo tài liệu Django.

Nếu được xác thực thành công,

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
16 cung cấp các thông tin đăng nhập sau:

  • https://postman-echo.com/basic-auth
    
    4 sẽ là một ví dụ Django
    https://postman-echo.com/basic-auth
    
    6.
  • https://postman-echo.com/basic-auth
    
    7 sẽ là
    import requests
    
    url = "https://postman-echo.com/basic-auth"
    username = "postman"
    password = "password"
    
    response = requests.get(url, auth=(username, password))
    print(response.status_code)
    print(response.json())
    
    3.

Các phản hồi không xác thực bị từ chối cho phép sẽ dẫn đến phản hồi

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
06.

  • Nếu bạn đang sử dụng API kiểu AJAX với sessionAuthentication, bạn sẽ cần đảm bảo rằng bạn bao gồm mã thông báo CSRF hợp lệ cho bất kỳ cuộc gọi phương thức HTTP "không an toàn" nào, chẳng hạn như
    <[]>
    200
    CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
    
    07,
    <[]>
    200
    CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
    
    08,
    <[]>
    200
    CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
    
    09 hoặc
    <[]>
    200
    CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
    
    10. Xem tài liệu Django CSRF để biết thêm chi tiết.
  • Cảnh báo: Luôn sử dụng chế độ xem đăng nhập tiêu chuẩn của Django khi tạo các trang đăng nhập. Điều này sẽ đảm bảo chế độ xem đăng nhập của bạn được bảo vệ đúng.

Xác thực CSRF trong Khung REST hoạt động hơi khác với DJANGO tiêu chuẩn do nhu cầu hỗ trợ cả xác thực phiên và không dựa trên phiên cho cùng một quan điểm. Điều này có nghĩa là chỉ các yêu cầu được xác thực mới yêu cầu mã thông báo CSRF và các yêu cầu ẩn danh mới có thể được gửi mà không cần mã thông báo CSRF. Hành vi này không phù hợp cho các chế độ xem đăng nhập, điều này phải luôn luôn áp dụng xác thực CSRF.

Điều khiển từ xa

Sơ đồ xác thực này cho phép bạn ủy quyền xác thực cho máy chủ web của mình, thiết lập biến môi trường

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
11.

Để sử dụng nó, bạn phải có

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
12 (hoặc một lớp con) trong cài đặt
<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
13 của bạn. Theo mặc định,
<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
14 tạo các đối tượng
https://postman-echo.com/basic-auth
6 cho các tên người dùng chưa tồn tại. Để thay đổi điều này và hành vi khác, hãy tham khảo tài liệu Django.

  • Nếu được xác thực thành công,
    <[]>
    200
    CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
    
    16 cung cấp các thông tin đăng nhập sau:
  • Tham khảo tài liệu của máy chủ web của bạn để biết thông tin về việc định cấu hình phương thức xác thực, ví dụ:

Apache Xác thực cách làm

Nginx (hạn chế quyền truy cập)


Lưu ý: Khi trình xác thực tùy chỉnh của bạn được gọi bởi các thuộc tính

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
35 hoặc
<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
36 của đối tượng yêu cầu, bạn có thể thấy một
<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
37 được tăng lại dưới dạng
<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
38. Điều này là cần thiết để ngăn chặn ngoại lệ ban đầu bị triệt tiêu bởi quyền truy cập thuộc tính bên ngoài. Python sẽ không nhận ra rằng
<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
37 bắt nguồn từ trình xác thực tùy chỉnh của bạn và thay vào đó sẽ cho rằng đối tượng yêu cầu không có thuộc tính
<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
35 hoặc
<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
36. Các lỗi này nên được sửa hoặc xử lý bởi trình xác thực của bạn.
When your custom authenticator is invoked by the request object's
<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
35 or
<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
36 properties, you may see an
<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
37 re-raised as a
<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
38. This is necessary to prevent the original exception from being suppressed by the outer property access. Python will not recognize that the
<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
37 originates from your custom authenticator and will instead assume that the request object does not have a
<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
35 or
<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
36 property. These errors should be fixed or otherwise handled by your authenticator.


Thí dụ

Ví dụ sau đây sẽ xác thực bất kỳ yêu cầu đến nào vì người dùng được đặt bởi tên người dùng trong tiêu đề yêu cầu tùy chỉnh có tên 'X-username'.

<[]>
401
CaseInsensitiveDict({'content-length': '1073', 'x-powered-by': 'Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.2.2 Java/Oracle Corporation/1.7)', 'expires': 'Thu, 01 Jan 1970 00:00:00 UTC', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'No-cache', 'cache-control': 'no-cache', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html', 'www-authenticate': 'Basic realm="controller_realm"'})
9

Gói của bên thứ ba

Các gói bên thứ ba sau đây cũng có sẵn.

django-rest-knox

Thư viện Django-Rest-Knox cung cấp các mô hình và chế độ xem để xử lý xác thực dựa trên mã thông báo theo cách an toàn và có thể mở rộng hơn so với sơ đồ Tokenauthentication tích hợp-với các ứng dụng trang và máy khách di động. Cung cấp các mã thông báo trên mỗi khách hàng và các chế độ xem để tạo chúng khi được cung cấp một số xác thực khác (thường là xác thực cơ bản), để xóa mã thông báo (cung cấp đăng nhập được thực thi của máy chủ) và để xóa tất cả các mã thông báo (đăng xuất tất cả các máy khách mà người dùng được đăng nhập vào ).

Gói công cụ Django OAuth cung cấp hỗ trợ OAuth 2.0 và hoạt động với Python 3.4+. Gói được duy trì bởi Jazzband và sử dụng oauthlib tuyệt vời. Gói được ghi lại tốt, và được hỗ trợ tốt và hiện là gói được đề xuất của chúng tôi cho hỗ trợ OAuth 2.0.recommended package for OAuth 2.0 support.

Cài đặt & Cấu hình

Cài đặt bằng

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
42.

https://postman-echo.com/basic-auth
0

Thêm gói vào

import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
7 của bạn và sửa đổi cài đặt khung REST của bạn.

https://postman-echo.com/basic-auth
1

Để biết thêm chi tiết, hãy xem Framework Django Rest - Bắt đầu tài liệu.

Django Rest Framework Oauth

Gói OAuth Django REST cung cấp cả hỗ trợ OAuth2 và OAuth2 cho khung REST.

Gói này trước đây được bao gồm trực tiếp trong khung REST nhưng hiện được hỗ trợ và duy trì dưới dạng gói của bên thứ ba.

Cài đặt & Cấu hình

Cài đặt bằng

<[]>
200
CaseInsensitiveDict({'content-encoding': 'gzip', 'x-powered-by': 'JSP/2.2', 'transfer-encoding': 'chunked', 'set-cookie': 'JSESSIONID=cb10906c6219c07f887dff5312fb; Path=/controller; HttpOnly', 'expires': 'Wed, 05 Nov 2014 19:03:37 GMT', 'server': 'nginx/1.1.19', 'connection': 'keep-alive', 'pragma': 'no-cache', 'cache-control': 'max-age=78000', 'date': 'Tue, 04 Nov 2014 21:23:37 GMT', 'content-type': 'text/html;charset=ISO-8859-1'})
42.

https://postman-echo.com/basic-auth
2

Thêm gói vào

import requests

url = "https://postman-echo.com/basic-auth"
header = {"Authorization" : "Basic cG9zdG1hbjpwYXNzd29yZA=="}

response = requests.get(url, headers=header)
print(response.status_code)
print(response.json())
7 của bạn và sửa đổi cài đặt khung REST của bạn.

Để biết thêm chi tiết, hãy xem Framework Django Rest - Bắt đầu tài liệu.

Django Rest Framework Oauth

Gói OAuth Django REST cung cấp cả hỗ trợ OAuth2 và OAuth2 cho khung REST.

Gói này trước đây được bao gồm trực tiếp trong khung REST nhưng hiện được hỗ trợ và duy trì dưới dạng gói của bên thứ ba.

Để biết chi tiết về cấu hình và sử dụng, hãy xem Tài liệu OAuth Framework Django REST để xác thực và quyền.

Xác thực mã thông báo web JSON

Mã thông báo JSON Web là một tiêu chuẩn khá mới có thể được sử dụng để xác thực dựa trên mã thông báo. Không giống như sơ đồ Tokenenauthentication tích hợp, xác thực JWT không cần phải sử dụng cơ sở dữ liệu để xác thực mã thông báo. Gói xác thực JWT là DjangorestFramework-SimpleJWT cung cấp một số tính năng cũng như ứng dụng Danh sách đen mã thông báo có thể cắm được.

Hawk HTTP Xác thực

Thư viện Hawkrest xây dựng trên Thư viện Mohawk để cho phép bạn làm việc với các yêu cầu và phản hồi đã ký Hawk trong API của bạn. Hawk cho phép hai bên giao tiếp an toàn với nhau bằng cách sử dụng các tin nhắn được ký bởi khóa chia sẻ. Nó dựa trên xác thực truy cập MAC HTTP (dựa trên các phần của OAuth 1.0).

Xác thực chữ ký HTTP

  • Chữ ký HTTP (hiện là bản nháp IETF) cung cấp một cách để đạt được xác thực gốc và tính toàn vẹn tin nhắn cho các tin nhắn HTTP. Tương tự như sơ đồ chữ ký HTTP của Amazon, được sử dụng bởi nhiều dịch vụ của mình, nó cho phép xác thực không có trạng thái, yêu cầu. Elvio Toccalino duy trì gói djangorestframework-httpsignature (lỗi thời) cung cấp cơ chế xác thực chữ ký HTTP dễ sử dụng. Bạn có thể sử dụng phiên bản Fork được cập nhật của DjangorestFramework-httpsignature, đó là DRF-HTTPSIG.
  • Djoser

Thư viện Djoser cung cấp một bộ lượt xem để xử lý các hành động cơ bản như đăng ký, đăng nhập, đăng nhập, đặt lại mật khẩu và kích hoạt tài khoản. Gói hoạt động với mô hình người dùng tùy chỉnh và sử dụng xác thực dựa trên mã thông báo. Điều này đã sẵn sàng để sử dụng triển khai nghỉ ngơi của hệ thống xác thực Django.

drfpasswordless

DrfPasswordless thêm (trung bình, tiền mặt lấy cảm hứng từ) hỗ trợ không có mật khẩu cho sơ đồ Tokenauthentication của Django Rest Framework. Người dùng đăng nhập và đăng ký bằng mã thông báo được gửi đến điểm liên hệ như địa chỉ email hoặc số điện thoại di động.

django-rest-authemail

Django-Rest-Authemail cung cấp giao diện API RESTful để đăng ký và xác thực người dùng. Địa chỉ email được sử dụng để xác thực, thay vì tên người dùng. Các điểm cuối API có sẵn để đăng ký, xác minh email đăng ký, đăng nhập, đăng xuất, đặt lại mật khẩu, xác minh đặt lại mật khẩu, thay đổi email, xác minh thay đổi email, thay đổi mật khẩu và chi tiết người dùng. Một dự án ví dụ đầy đủ chức năng và các hướng dẫn chi tiết được bao gồm.

Django-Rest-Durin

Django-Rest-Durin được xây dựng với ý tưởng có một thư viện có mã thông báo cho nhiều máy khách API Web/CLI/Mobile thông qua một giao diện nhưng cho phép cấu hình mã thông báo khác nhau cho mỗi ứng dụng API tiêu thụ API. Nó cung cấp hỗ trợ cho nhiều mã thông báo cho mỗi người dùng thông qua các mô hình tùy chỉnh, chế độ xem, quyền hoạt động với Django-Rest-FrameWorks. Thời gian hết hạn mã thông báo có thể khác nhau cho mỗi ứng dụng API và có thể tùy chỉnh thông qua giao diện quản trị Django.

Thêm thông tin có thể được tìm thấy trong tài liệu.