來呀~
用戶模塊
Json Web Token認證
最常見的認證機制
Session認證
Token認證
Session認證
保持在服務端,增加服務器開銷
分佈式架構中,難以維持Session會話同步
CSRF攻擊風險(跨站請求)
Token認證
保存在客戶端
跨語言,跨平臺
擴展性強
鑑權性能高
JWT(Json Web Token)
由三部分組成
header
聲明類型
聲明加密算法
base64加密,可以解密
playload
存放過期時間,簽發用戶等
可以添加用戶的非敏感信息
base64加密,可以解密
signature
由三部分組成
使用base64加密之後的header + . + 使用base64加密之後的playload + 使用HS256算法加密,同時secret加鹽處理
安裝djangorestframework-jwt
$ pip install djangorestframework-jwt
使用
在 setting.py
中添加
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
# 使用JWT Token認證
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
# Basic類型的認證(賬號和密碼)
'rest_framework.authentication.SessionAuthentication',
# Session會話認證
'rest_framework.authentication.BasicAuthentication',
],
}
添加路由
用戶處:user/urls.py
from django.urls import path
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
path('login/', obtain_jwt_token),
]
主路由:
ApiTest/urls.py
urlpatterns = [
path('users/', include('user.urls'))
]
不登錄的訪問
登錄後的返回內容
HTTP 200 OK
Allow: POST, OPTIONS
Content-Type: application/json
Vary: Accept
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6Inpob25neGluIiwiZXhwIjoxNTcyMzA5MzQ2LCJlbWFpbCI6IjQ5MDMzNjUzNEBxcS5jb20ifQ.ZDEeBAgSuPyvh1KBnF1sSY9w22guSRHXm8sbgqEWusg"
}
import base64
base64.b64decode('eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9')
# b'{"typ":"JWT","alg":"HS256"}'
認證過期時間
./site-packages/rest_framework_jwt/settings.py
第40行
'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300),
Token默認過期時間5分鐘
自行修改過期時間 ApiTest/settings.py
過期時間爲1天
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1)
}
請求Token 頭
'JWT_AUTH_HEADER_PREFIX': 'JWT',
使用httpie發起包含token的內容
安裝 httpie-jwt-auth
插件
$ export JWT_AUTH_TOKEN='你的token'
$ export JWT_AUTH_PREFIX='JWT'
$ http -A jwt :8000/projects/ page==2 size==2
修改載荷
def jwt_response_payload_handler(token, user=None, request=None):
"""
Returns the response data for both the login and refresh views.
Override to return a custom response such as including the
serialized representation of the User.
Example:
def jwt_response_payload_handler(token, user=None, request=None):
return {
'token': token,
'user': UserSerializer(user, context={'request': request}).data
}
"""
return {
'token': token
}
在 utils/jwt_handler.py
重寫
def jwt_response_payload_handler(token, user=None, request=None):
return {
'token': token,
'user_id': user.id,
'username': user.username,
}
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
'JWT_PAYLOAD_GET_USERNAME_HANDLER': 'utils.jwt_handler.jwt_response_payload_handler'
}
Django自帶的用戶模型
django.contrib.auth.models.User
查看settings.py可以發現,默認註冊了 django.contrib.auth
註冊
用戶名(6-20位,不重複)
郵箱(符合郵箱格式)
密碼(6-20位,和確認密碼一致)
確認密碼(6-20位,和密碼一致)
user/serializers.py
from rest_framework import serializers
from django.contrib.auth.models import User
class RegisterSerializer(serializers.ModelSerializer):
password_conform = serializers.CharField(label='確認密碼',
min_length=6,
max_length=20,
write_only=True,
help_text='確認密碼',
error_messages={'min_length': '僅允許6~20個字符的確認密碼',
'max_length': '僅允許6~20個字符的確認密碼'}
)
token = serializers.CharField(label='生成token',
read_only=True)
class Meta:
model = User
fields = ('id', 'username', 'password', 'email', 'password_conform', 'token')
extra_kwargs = {
'username': {
'label': '用戶名',
'help_text': '用戶名',
'min_length': 6,
'max_length': 20,
'error_messages': {'min_length': '僅允許6~20個字符的用戶名',
'max_length': '僅允許6~20個字符的用戶名'}
},
'email': {
'label': '郵箱',
'help_text': '郵箱',
'write_only': True,
'required': True
},
'password': {
'label': '密碼',
'help_text': '密碼',
'write_only': True,
'min_length': 6,
'max_length': 20,
'error_messages': {'min_length': '僅允許6~20個字符的密碼',
'max_length': '僅允許6~20個字符的密碼'}
}
}
def create(self, validated_data):
pass
user/urls.py
from django.urls import path
from rest_framework_jwt.views import obtain_jwt_token
from . import views
urlpatterns = [
path('login/', obtain_jwt_token),
path('register/', views.RegisterView.as_view()),
]
user/views.py
from rest_framework.generics import CreateAPIView
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from user.serializers import RegisterSerializer
class RegisterView(CreateAPIView):
serializer_class = RegisterSerializer
authentication_classes = (JSONWebTokenAuthentication,)