From f9acb2a12031b68be7c51fa046c41ca1e2046240 Mon Sep 17 00:00:00 2001 From: roger_home_pc Date: Sun, 3 Sep 2023 21:15:58 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E9=AA=8C=E8=AF=81=E7=9A=84?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E5=AD=A6=E4=B9=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/goods/urls.py | 19 ++++++++++++++++++- apps/goods/views_viewset.py | 5 +++++ common/myjwt.py | 11 +++++++++++ common/mypermissions.py | 15 +++++++++++++++ myshop_back/settings.py | 28 ++++++++++++++++++++++++++-- 5 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 common/myjwt.py create mode 100644 common/mypermissions.py diff --git a/apps/goods/urls.py b/apps/goods/urls.py index 549a54c..92f4cd3 100644 --- a/apps/goods/urls.py +++ b/apps/goods/urls.py @@ -18,6 +18,12 @@ from django.contrib import admin from django.urls import path, include from apps.goods import views, views_api, views_apiview, views_mixin, views_generics, views_viewset from rest_framework.routers import DefaultRouter +from rest_framework.documentation import include_docs_urls +from rest_framework.schemas import get_schema_view +from rest_framework_swagger.renderers import SwaggerUIRenderer, OpenAPICodec +from rest_framework.authtoken.views import obtain_auth_token +from rest_framework_jwt.views import obtain_jwt_token +from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView, TokenVerifyView goods_list = views_viewset.GoodsViewSet.as_view({ 'get': 'list', @@ -32,6 +38,7 @@ goods_detail = views_viewset.GoodsViewSet.as_view({ router = DefaultRouter() router.register('goods_custom', views_viewset.GoodsViewSetCustom, basename='goods_custom') +schema_view = get_schema_view(title='Swagger接口文档', renderer_classes=[OpenAPICodec, SwaggerUIRenderer]) urlpatterns = [ # path('cate_index/', views.GoodCateView.as_view(), name='cate_index'), @@ -52,5 +59,15 @@ urlpatterns = [ path('goods_viewset/', goods_list), path('goods_viewset//', goods_detail), - path('', include(router.urls)) + path('', include(router.urls)), + path('docs/', include_docs_urls(title='接口文档')), + path('docs_swagger/', schema_view, name='docs'), + + path('api_token-auth/', obtain_auth_token), + path('api-jwt-token-auth/', obtain_jwt_token), + + path('api-auth', include('rest_framework.urls', namespace='rest_framework')), + path('api-simplejwt-token/', TokenObtainPairView.as_view(), name='token_obtain_pair'), + path('api-simplejwt-token/refresh/', TokenRefreshView.as_view(), name='token_refresh'), + path('api-simplejwt-token/verify/', TokenVerifyView.as_view(), name='token_verify'), ] diff --git a/apps/goods/views_viewset.py b/apps/goods/views_viewset.py index 39213f6..743a715 100644 --- a/apps/goods/views_viewset.py +++ b/apps/goods/views_viewset.py @@ -10,6 +10,10 @@ from common.mypagination import MyPagination from common.myfilter import MyFilter from common.mymodelviewset import MyModelViewSet +from rest_framework import permissions +from rest_framework.authentication import TokenAuthentication +# from common + class GoodsViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, @@ -29,6 +33,7 @@ class GoodsViewSet(mixins.ListModelMixin, search_fields = ('name', 'price') # 排序 ordering_fields = ('id', 'name', 'price') + permission_classes = (permissions.IsAuthenticated,) class GoodsDetailViewSet(viewsets.ReadOnlyModelViewSet): diff --git a/common/myjwt.py b/common/myjwt.py new file mode 100644 index 0000000..485727a --- /dev/null +++ b/common/myjwt.py @@ -0,0 +1,11 @@ +import rest_framework.permissions + + +def jwt_response_payload_handler(token, user=None, request=None): + return { + 'token': token, + 'id': user.id, + 'username': user.username, + 'email': user.email, + 'is_active': user.is_active, + } diff --git a/common/mypermissions.py b/common/mypermissions.py new file mode 100644 index 0000000..171364e --- /dev/null +++ b/common/mypermissions.py @@ -0,0 +1,15 @@ +from rest_framework.permissions import BasePermission +from rest_framework_jwt.authentication import jwt_decode_handler + + +class IsOwnerOrReadOnly(BasePermission): + def has_permission(self, request, view): + if request.user.username == 'admin': + return True + + def has_object_permission(self, request, view, obj): + token = request.META['HTTP_AUTHORIZATION'][5:] + token_user = jwt_decode_handler(token) # 解析token + if token_user: + return obj.user.id == token_user['user_id'] + return False diff --git a/myshop_back/settings.py b/myshop_back/settings.py index 509854e..e1ece81 100644 --- a/myshop_back/settings.py +++ b/myshop_back/settings.py @@ -9,7 +9,7 @@ https://docs.djangoproject.com/en/4.2/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/4.2/ref/settings/ """ - +import datetime from pathlib import Path import sys, os @@ -45,10 +45,14 @@ INSTALLED_APPS = [ 'ckeditor', 'ckeditor_uploader', 'rest_framework', - 'django_filters' + 'django_filters', + 'rest_framework_swagger', + 'rest_framework.authtoken', + 'corsheaders', ] MIDDLEWARE = [ + 'corsheaders.middleware.CorsMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', @@ -146,6 +150,7 @@ auth.User.groups: (fields.E304) Reverse accessor 'Group.user_set' for 'auth.User """ AUTH_USER_MODEL = 'user.Myuser' + REST_FRAMEWORK = { # 设置全局渲染模板 'DEFAULT_RENDERER_CLASSES': ( @@ -159,4 +164,23 @@ REST_FRAMEWORK = { # 设置筛选模板 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',), 'EXCEPTION_HANDLER': 'common.myexception.my_exception_handler', + 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema', + # 验证设置 + 'DEFAULT_AUTHENTICATION_CLASSES': ('rest_framework_simplejwt.authentication.JWTAuthentication', ), + 'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAuthenticated',), +} +JWT_AUTH = { + 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=3), # 配置过期时间 + 'JWT_AUTH_HEADER_PREFIX': 'JWT', # 配置Token的前缀 + 'JWT_ALLOW_REFRESH': False, # 是否允许刷新 + 'JWT_RESPONSE_PAYLOAD_HANDLER': 'common.myjwt.jwt_response_payload_handler', } + +SIMPLE_JWT = { + 'ACCESS_TOKEN_LIFETIME': datetime.timedelta(minutes=30), # token有效时长 + 'REFRESH_TOKEN_LIFETIME': datetime.timedelta(days=1), # token刷新有效时长 +} + +# 跨域配置 +CORS_ALLOW_CREDENTIALS = True # 跨域时是否携带cookie +CORS_ORIGIN_ALLOW_ALL = True # 指定所有域名都可以访问后端接口