測試開發進階(三十一)

來呀~

用戶模塊

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

  1. $ pip install djangorestframework-jwt

使用

setting.py中添加

  1. REST_FRAMEWORK = {

  2. 'DEFAULT_AUTHENTICATION_CLASSES': [

  3. # 使用JWT Token認證

  4. 'rest_framework_jwt.authentication.JSONWebTokenAuthentication',

  5. # Basic類型的認證(賬號和密碼)

  6. 'rest_framework.authentication.SessionAuthentication',

  7. # Session會話認證

  8. 'rest_framework.authentication.BasicAuthentication',

  9. ],

  10. }

添加路由

用戶處:user/urls.py

  1. from django.urls import path

  2. from rest_framework_jwt.views import obtain_jwt_token

  3. urlpatterns = [

  4. path('login/', obtain_jwt_token),

  5. ]

主路由:

ApiTest/urls.py

  1. urlpatterns = [

  2. path('users/', include('user.urls'))

  3. ]

不登錄的訪問

登錄後的返回內容

  1. HTTP 200 OK

  2. Allow: POST, OPTIONS

  3. Content-Type: application/json

  4. Vary: Accept

  5. {

  6. "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6Inpob25neGluIiwiZXhwIjoxNTcyMzA5MzQ2LCJlbWFpbCI6IjQ5MDMzNjUzNEBxcS5jb20ifQ.ZDEeBAgSuPyvh1KBnF1sSY9w22guSRHXm8sbgqEWusg"

  7. }

  1. import base64

  2. base64.b64decode('eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9')

  3. # b'{"typ":"JWT","alg":"HS256"}'

認證過期時間

./site-packages/rest_framework_jwt/settings.py

第40行

  1. 'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300),

Token默認過期時間5分鐘

自行修改過期時間 ApiTest/settings.py

過期時間爲1天

  1. JWT_AUTH = {

  2. 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1)

  3. }

請求Token 頭

  1. 'JWT_AUTH_HEADER_PREFIX': 'JWT',

使用httpie發起包含token的內容

安裝 httpie-jwt-auth插件

  1. $ export JWT_AUTH_TOKEN='你的token'

  2. $ export JWT_AUTH_PREFIX='JWT'

  3. $ http -A jwt :8000/projects/ page==2 size==2

修改載荷

  1. def jwt_response_payload_handler(token, user=None, request=None):

  2. """

  3. Returns the response data for both the login and refresh views.

  4. Override to return a custom response such as including the

  5. serialized representation of the User.

  6. Example:

  7. def jwt_response_payload_handler(token, user=None, request=None):

  8. return {

  9. 'token': token,

  10. 'user': UserSerializer(user, context={'request': request}).data

  11. }

  12. """

  13. return {

  14. 'token': token

  15. }

utils/jwt_handler.py重寫

  1. def jwt_response_payload_handler(token, user=None, request=None):

  2. return {

  3. 'token': token,

  4. 'user_id': user.id,

  5. 'username': user.username,

  6. }

  1. JWT_AUTH = {

  2. 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),

  3. 'JWT_PAYLOAD_GET_USERNAME_HANDLER': 'utils.jwt_handler.jwt_response_payload_handler'

  4. }

Django自帶的用戶模型

django.contrib.auth.models.User

查看settings.py可以發現,默認註冊了 django.contrib.auth

註冊

  • 用戶名(6-20位,不重複)

  • 郵箱(符合郵箱格式)

  • 密碼(6-20位,和確認密碼一致)

  • 確認密碼(6-20位,和密碼一致)

user/serializers.py

  1. from rest_framework import serializers

  2. from django.contrib.auth.models import User

  3. class RegisterSerializer(serializers.ModelSerializer):

  4. password_conform = serializers.CharField(label='確認密碼',

  5. min_length=6,

  6. max_length=20,

  7. write_only=True,

  8. help_text='確認密碼',

  9. error_messages={'min_length': '僅允許6~20個字符的確認密碼',

  10. 'max_length': '僅允許6~20個字符的確認密碼'}

  11. )

  12. token = serializers.CharField(label='生成token',

  13. read_only=True)

  14. class Meta:

  15. model = User

  16. fields = ('id', 'username', 'password', 'email', 'password_conform', 'token')

  17. extra_kwargs = {

  18. 'username': {

  19. 'label': '用戶名',

  20. 'help_text': '用戶名',

  21. 'min_length': 6,

  22. 'max_length': 20,

  23. 'error_messages': {'min_length': '僅允許6~20個字符的用戶名',

  24. 'max_length': '僅允許6~20個字符的用戶名'}

  25. },

  26. 'email': {

  27. 'label': '郵箱',

  28. 'help_text': '郵箱',

  29. 'write_only': True,

  30. 'required': True

  31. },

  32. 'password': {

  33. 'label': '密碼',

  34. 'help_text': '密碼',

  35. 'write_only': True,

  36. 'min_length': 6,

  37. 'max_length': 20,

  38. 'error_messages': {'min_length': '僅允許6~20個字符的密碼',

  39. 'max_length': '僅允許6~20個字符的密碼'}

  40. }

  41. }

  42. def create(self, validated_data):

  43. pass

user/urls.py

  1. from django.urls import path

  2. from rest_framework_jwt.views import obtain_jwt_token

  3. from . import views

  4. urlpatterns = [

  5. path('login/', obtain_jwt_token),

  6. path('register/', views.RegisterView.as_view()),

  7. ]

user/views.py

  1. from rest_framework.generics import CreateAPIView

  2. from rest_framework_jwt.authentication import JSONWebTokenAuthentication

  3. from user.serializers import RegisterSerializer

  4. class RegisterView(CreateAPIView):

  5. serializer_class = RegisterSerializer

  6. authentication_classes = (JSONWebTokenAuthentication,)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章