drf笔记

Django-restframework

  __init__.py

 import pymysql
 pymysql.install_as_MySQLdb()
setting.py
 # Mysql
 DATABASES = {
     'default': {
         'ENGINE': 'django.db.backends.mysql',  # 数据库引擎
         'NAME': 'xuanjian',  # 数据库名
         'USER': 'xuanjian_root',  # 账号
         'PASSWORD': '',  # 密码
         'HOST': '127.0.0.1',  # HOST
         'POST': 3306,  # 端口
         'OPTIONS': {
             'init_command': 'SET sql_mode="STRICT_TRANS_TABLES"',
             'charset': 'utf8mb4'
         }
     }
 }
 ​
 # drf配置
 REST_FRAMEWORK = {
     # 全局使用的认证类
     "DEFAULT_AUTHENTICATION_CLASSES": [
         'yourapp.auth.MyAuth',
         'yourapp.auth.PasswordAuth',
     ],
     'DATETIME_FORMAT': '%Y-%m-%d %H:%M:%S',
     'EXCEPTION_HANDLER': 'yourapp.exception.exception_handler',  # 全局配置异常模块
     'DEFAULT_RENDERER_CLASSES': (
         'yourapp.render.CustomRenderer',  # 设置自定义返回数据格式
     ),
 }
 ​
 # 更改MyUser为用户表
 AUTH_USER_MODEL = 'yourapp.Users'
 ​
 # sm4加密key
 SM4_KEY = "KGc3zITWUAzcxQa4"
 ​
 # 自定义加密方式
 PASSWORD_HASHERS = (
      'yourapp.hashers.SM4PasswordHasher',
  )
 ​
 # 配置 MEDIA_ROOT 作为你上传文件在服务器中的基本路径
 MEDIA_ROOT = os.path.join(BASE_DIR, 'upload')  # 注意此处不要写成列表或元组的形式
 # 配置 MEDIA_URL 作为公用 URL,指向上传文件的基本路径
 MEDIA_URL = '/media/'
 # 这里特意写成 upload 和 media,而不是统一写成 media 或 upload,是为了便于理解 MEDIA_ROOT 和 MEDIA_URL 的作用和区别
 ​
 # 自定义账号密码认证
 AUTHENTICATION_BACKENDS = [
     'django.contrib.auth.backends.ModelBackend',
     'yourapp.auth.PasswordAuth'
 ]

urls.py

 urlpatterns = [
     path('', include('yourapp.urls')),
     url(r'media/(?P.*)$', serve, {'document_root': settings.MEDIA_ROOT})
 ]

yourapp/auth.py

 import datetime
 ​
 from django.contrib.auth.backends import ModelBackend
 from rest_framework import exceptions
 ​
 from xuanjian.models import Users, Tokens
 from xuanjian.sm4 import SM4EncryptDecrypt
 ​
 # 全局加密解密对象
 sm4 = SM4EncryptDecrypt()
 ​
 ​
 class MyAuth:
     def authenticate(self, request):
         # 该示例认证是需要在请求的url加上参数token(实际直接是校验用户名或密码或者登陆标识等)
         token = request.headers.get('Token')
         token_obj = Tokens.objects.filter(token=token).first()
         if not token_obj:
             raise exceptions.AuthenticationFailed('未认证用户!')
         elif token_obj.valid_time < datetime.datetime.utcnow():
             token_obj.delete()
             raise exceptions.AuthenticationFailed('认证失效!')
         else:
             user_obj = token_obj.user_set.all().first()
             if not user_obj.is_active:
                 raise exceptions.AuthenticationFailed('账户已冻结!')
             else:
                 return user_obj, 'request.auth'  # 认证函数执行结果如果通过则为元组,元组第一个元素封装在为request.user,第二个元素封装为request.auth
 ​
     def authenticate_header(self, request):
         pass
 ​
 ​
 class PasswordAuth(ModelBackend):
     def authenticate(self, request, username=None, password=None, **kwargs):
         if username and password:
             user = Users.objects.filter(username=username, password=sm4.encrypt(password), is_active=True)
             if user:
                 return user.first()
 ​
         return None
yourapp/exception.py
 from rest_framework.views import exception_handler as drf_exception_handler
 from rest_framework.response import Response
 from rest_framework import status
 ​
 ​
 def exception_handler(exc, context):
     response = drf_exception_handler(exc, context)
     print(exc, context)
     if not response:  # 服务端错误
         response = Response({'detail': '服务器内部错误,{}:{}'.format(context['view'], exc)},
                             status=status.HTTP_500_INTERNAL_SERVER_ERROR)
     return response
yourapp/hashers.py
 from django.contrib.auth.hashers import BasePasswordHasher
 ​
 from xuanjian.sm4 import SM4EncryptDecrypt
 ​
 ​
 class SM4PasswordHasher(BasePasswordHasher):
     algorithm = "mymd5"
     # 全局加密解密对象
     sm4 = SM4EncryptDecrypt()
 ​
     def encode(self, password, salt):
         assert password is not None
         return self.sm4.encrypt(password)
 ​
     def verify(self, password, encoded):
         encoded_2 = self.sm4.encrypt(password)
         return encoded == encoded_2
 ​
     def decode(self, encoded):
         return self.sm4.decrypt(encoded)
 ​
     def safe_summary(self, encoded):
         return {'algorithm': self.algorithm, 'salt': '', 'hash': ''}
yourapp/models.py
 from datetime import datetime
 ​
 from django.contrib.auth.models import AbstractUser, Group, Permission
 from django.contrib.contenttypes.models import ContentType
 from django.db import models
 ​
 # Create your models here.
 ​
 # 文件上传,名字自定义
 def custom_upload_path(instance, filename):
     folder = instance.__class__.__name__.lower()
     date_str = "%s%02d%02d%02d%02d%02d" % (datetime.now().year, datetime.now().month, datetime.now().day,
                                            datetime.now().hour, datetime.now().minute, datetime.now().second)
     filename = filename.split('.')[0] + '_' + date_str + "." + filename.split('.')[-1]
     return "{}/{}".format(folder, filename)
 ​
 ​
 # 用户模型
 class Users(AbstractUser):
     """
     用户表,继承于默认用户表
     """
     sex = models.BooleanField(default=True, verbose_name='性别')
     birthday = models.DateField(blank=True, null=True, verbose_name='生日')
     phone = models.CharField(max_length=11, null=True, verbose_name='联系方式')
     image = models.ImageField(upload_to=custom_upload_path, null=True, verbose_name='头像')
     token = models.ForeignKey('Tokens', on_delete=models.SET_NULL, null=True, related_name="user_set",
                               related_query_name="user", verbose_name='用户Token')
     update_time = models.DateTimeField(help_text='修改时间', auto_now=True)
 ​
     class Meta:
         db_table = 'users'

yourapp/render.py

 from rest_framework.renderers import JSONRenderer
 ​
 ​
 class CustomRenderer(JSONRenderer):
     # 重构render方法
     def render(self, data, accepted_media_type=None, renderer_context=None):
         if not data.get('code', None):
             data = {
                 'code': 500,
                 'message': '服务器错误',
                 'result': data
             }
         return super().render(data, accepted_media_type, renderer_context)

sm4.py

from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT
import binascii

from xuanjian_python.settings import SM4_KEY


class SM4EncryptDecrypt:
    """
    国密sm4加解密
    """

    def __init__(self):
        self.encrypt_key = SM4_KEY
        self.decrypt_key = SM4_KEY
        self.crypt_sm4 = CryptSM4()

    def str_to_hexStr(self, hex_str):
        """
        字符串转hex
        :param hex_str: 字符串
        :return: hex
        """
        hex_data = hex_str.encode('utf-8')
        str_bin = binascii.unhexlify(hex_data)
        return str_bin.decode('utf-8')

    def encrypt(self, value):
        """
        国密sm4加密
        # :param encrypt_key: sm4加密key
        :param value: 待加密的字符串
        :return: sm4加密后的hex值
        """
        crypt_sm4 = self.crypt_sm4
        crypt_sm4.set_key(self.encrypt_key.encode(), SM4_ENCRYPT)
        encrypt_value = crypt_sm4.crypt_ecb(value.encode())  # bytes类型
        return encrypt_value.hex()

    def decrypt(self, encrypt_value):
        """
        国密sm4解密
        # :param decrypt_key:sm4加密key
        :param encrypt_value: 待解密的hex值
        :return: 原字符串
        """
        crypt_sm4 = self.crypt_sm4
        crypt_sm4.set_key(self.decrypt_key.encode(), SM4_DECRYPT)
        decrypt_value = crypt_sm4.crypt_ecb(bytes.fromhex(encrypt_value))  # bytes类型
        return self.str_to_hexStr(decrypt_value.hex())


if __name__ == '__main__':
    # str_data = {"ffffffwsdwefewd": "fefefewfwrv", "qazqaz": "vfbfrbgtrnujy"}
    str_data = '123456789'
    SM4 = SM4EncryptDecrypt()
    print("待加密内容:", str_data)
    encoding = SM4.encrypt(str(str_data))
    print("国密sm4加密后的结果:", encoding)
    print("国密sm4解密后的结果:", SM4.decrypt('f8943bcda25190019cbcbadabdbaf3c7'))

你可能感兴趣的:(django,restful,python)