bifangback

bifangback-在django restframework

2020-12-29  本文已影响0人  万州客

上次metis干过一次,这次bifang,还可以再干一次塞。

一,安装第三方库

1,django跨域django-cors-headers

pip install django-cors-headers

2,DRF(django restframework)安装

pip install djangorestframework

3,DRF的JWT认证安装

pip install djangorestframework-jwt

二,配置settings.py文件

配置重点关注内容如下:

# Application definition

INSTALLED_APPS = [
    'account.apps.AccountConfig',
    'app.apps.AppConfig',
    'cmdb.apps.CmdbConfig',
    'deploy.apps.DeployConfig',
    'env.apps.EnvConfig',
    'log.apps.LogConfig',
    'release.apps.ReleaseConfig',
    'server.apps.ServerConfig',
    ...
    'rest_framework',
    'corsheaders',
]

MIDDLEWARE = [
    ...
    'django.contrib.sessions.middleware.SessionMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    ...
]

LANGUAGE_CODE = 'zh-hans'

TIME_ZONE = 'Asia/Shanghai'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/

STATIC_URL = '/static/'

CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True

CORS_ORIGIN_WHITELIST = [
    "https://example.com",
    "https://sub.example.com",
    "http://localhost:8080",
    "http://localhost:8000",
    "http://127.0.0.1:8000"
]

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

# 自定义obtain_jwt_token登录参数验证
AUTHENTICATION_BACKENDS = (
    'account.jwt_views.CustomJwtBackend',
)
JWT_AUTH = {
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=365),
    'JWT_AUTH_HEADER_PREFIX': 'Bearer',
    'JWT_ALLOW_REFRESH': True,
}

三,settings中定义的account/jwt_views.py内容

from datetime import datetime
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
from rest_framework import status
from rest_framework.response import Response
from rest_framework_jwt.settings import api_settings
from rest_framework_jwt.views import JSONWebTokenAPIView
from rest_framework_jwt.views import ObtainJSONWebToken
from rest_framework_jwt.views import RefreshJSONWebToken
from rest_framework_jwt.views import VerifyJSONWebToken
from django.contrib.auth import get_user_model

User = get_user_model()


class CustomJwtBackend(ModelBackend):
    """
    自定义用户验证,定义完之后还需要在settings中进行配置
    """
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            user = User.objects.get(Q(username=username) | Q(email=username))
            # django里面的password是加密的,前端传过来的password是明文,
            # 调用check_password就会对明文进行加密,比较两者是否相同
            if user.check_password(password):
                return user
        except Exception as e:
            return None


# 不改rest_framework_jwt源码的情况下,自定义登陆后成功和错误的返回,最优雅
def jwt_response_payload_handler(token, user=None, expiration=None):
    """
    自定义jwt认证成功返回数据
    """
    data = {
        'token': token,
        'expireAt': expiration,
        'user_id': user.id,
        'user': {
            'id': user.id,
            'name': user.username,
            'email': user.email,
            'avatar': ''},
        'is_superuser': user.is_superuser,
        'permissions': [{'id': 'queryForm', 'operation': ['add', 'edit']}],
        'roles': [{'id': 'admin', 'operation': ['add', 'edit', 'delete']}],
    }
    return {'code': 0, 'message': '欢迎回来', 'data': data}


def jwt_response_payload_error_handler(serializer, requst=None):
    """
    自定义jwt认证错误返回数据
    """
    data = {
        'message': "用户名或者密码错误",
        'status': 400,
        'detail': serializer.errors,
    }
    return {'code': -1, 'data': data}


# jwt的返回,由JSONWebTokenAPIView,自定义它的调用和返回即可
class CustomWebTokenAPIView(JSONWebTokenAPIView):
    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            user = serializer.object.get('user') or request.user
            token = serializer.object.get('token')
            expiration = (datetime.utcnow() +
                          api_settings.JWT_EXPIRATION_DELTA)
            response_data = jwt_response_payload_handler(token, user, expiration)
            response = Response(response_data)
            if api_settings.JWT_AUTH_COOKIE:
                response.set_cookie(api_settings.JWT_AUTH_COOKIE,
                                    token,
                                    expiration=expiration,
                                    httponly=True)
            return response
        error_data = jwt_response_payload_error_handler(serializer, request)
        return Response(error_data, status=status.HTTP_200_OK)


class CustomObtainJSONWebToken(ObtainJSONWebToken, CustomWebTokenAPIView):
    pass


class CustomRefreshJSONWebToken(RefreshJSONWebToken, CustomWebTokenAPIView):
    pass


class CustomVerifyJSONWebToken(VerifyJSONWebToken, CustomWebTokenAPIView):
    pass


obtain_jwt_token = CustomObtainJSONWebToken.as_view()
refresh_jwt_token = CustomRefreshJSONWebToken.as_view()
verity_jwt_token = CustomVerifyJSONWebToken.as_view()

这个文件,不但包含了jwt认证的后端,还改写了obtain_jwt_token ..等几个函数,在接下来的Urls.py中有用。

四,定义urls.py的路由

urls.py

from account import jwt_views
urlpatterns = [
    path('', index, name='index'),
    path('admin/', admin.site.urls),
    path('api-auth/', include('rest_framework.urls')),
    path('jwt_auth/', jwt_views.obtain_jwt_token),
    path('refresh_jwt_auth/', jwt_views.refresh_jwt_token),
    path('verify_jwt_auth/', jwt_views.verity_jwt_token),
]

五,测试jwt认证

postman上


2020-12-29 22_13_29-Postman.png

这个返回内容,要根据整个项目的认证和权限体系,在后期慢慢调整的。

{
    "code": 0,
    "message": "欢迎回来",
    "data": {
        "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNjQwNzg2MTE5LCJlbWFpbCI6ImFkbWluQGRlbW8uY29tIiwib3JpZ19pYXQiOjE2MDkyNTAxMTl9.ODHTz_Y3TFQx9WxSDLPrR867JJT31SPcMUGnsKOs6Qk",
        "expireAt": "2021-12-29T13:55:19.072310",
        "user_id": 1,
        "user": {
            "id": 1,
            "name": "admin",
            "email": "admin@demo.com",
            "avatar": ""
        },
        "is_superuser": true,
        "permissions": [
            {
                "id": "queryForm",
                "operation": [
                    "add",
                    "edit"
                ]
            }
        ],
        "roles": [
            {
                "id": "admin",
                "operation": [
                    "add",
                    "edit",
                    "delete"
                ]
            }
        ]
    }
}
上一篇下一篇

猜你喜欢

热点阅读