django restframe jwt自定义(一)

本文根据实际使用讲解jwt配置和常用的方法

先贴上我的django settings

"""
Django settings for zklf_manage_platform project.

Generated by 'django-admin startproject' using Django 2.1.5.

For more information on this file, see
https://docs.djangoproject.com/en/2.1/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.1/ref/settings/
"""

import os
# from mongoengine import register_connection
import datetime

# ******************************************************************
GD_KEY = ""  # 高德地图开发者平台key
# variable
# redis
# REDIS_HOST = ""
REDIS_HOST = ""
# msyql
MYSQL_ADDRESS_PRO = ""
MYSQL_ACCOUND_PRO = ""
MYSQL_PASS_PRO = ''
MYSQL_DB_NAME_PRO = ''

MYSQL_ADDRESS_LOCAL = ""
MYSQL_ACCOUND_LOCAL = ""
MYSQL_PASS_LOCAL = ''

MONGODBIP_AI_ZKLF = ""
MONGODBPORT_AI_ZKLF = 27017
MONGODB_ACCOUNT_AI_ZKLF = ""
MONGODB_PASS_AI_ZKLF = ""
DATABASE_AI_ZKLF_IMAGE = ""

#  kml文件保存地址
MONGODBPORT_ADDR = ""
MONGODBIP_VIS_SYSTEM = "192.168."
MONGODBPORT_VIS_SYSTEM = 27017
MONGODB_ACCOUNT_VIS_SYSTEM = ""
MONGODB_PASS_VIS_SYSTEM = ""
DATABASE_VIS_SYSTEM = ""

# seafile服务器地址
SEAFILE_ADDR_BJ = ""
SEAFILE_USER = ""
SEAFILE_PASSWORD = ""

# ******************************************************************

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '*=tb3v%!c&j$jk(3il9dhbre1=g)tr@)p27ouy%4=fp37upbni'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ['*']
APPEND_SLASH = True
DATA_UPLOAD_MAX_MEMORY_SIZE = 3621440000  # 设置上传请求的最大字节为3.37G


# Application definition
'''
django.contrib.admin -- 管理员站点, 你很快就会使用它。
django.contrib.auth -- 认证授权系统。
django.contrib.contenttypes -- 内容类型框架。
django.contrib.sessions -- 会话框架。
django.contrib.messages -- 消息框架。
django.contrib.staticfiles -- 管理静态文件的框架。
'''

INSTALLED_APPS = [
    'rest_framework',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'corsheaders',
    'rest_framework_swagger',
    'mongoengine',
    'util',
 
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    # 'corsheaders.middleware.CorsMiddleware',
    # LocaleMiddleware中间件需要放在sessions中间件之后和common中间件之前。
    # 因为LocaleMiddleware需要使用session的数据,而common需要有一个激活的语言来解析URL。
    'django.middleware.locale.LocaleMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

# Backend可以是普通的python类,但是关于登陆校验需要具有以下规定的2个方法:
# authenticate(self,username=None,password=None) 或者authenticate(self,token=None),如果通过验证,返回值是一个User对象,如果不通过验证,返回值是None。
# get_user(self,user_id)
# 这两类方法的具体使用不是很相同,关于登陆校验的authenticate,Django在使用他们的时候,会遍历所有的auth backends
# 一旦发现有一个backend校验通过,即返回User对象,那么将会停止下面backend的校验,并且将校验成功的backend绑定在该用户上放入session中,
# 此后如果再次调用该方法,那么将会使用session中的backend进行校验,而不再遍历所有backend了。
AUTHENTICATION_BACKENDS = ['util.auth_func.CustomBackend']


REST_FRAMEWORK = {
    # api文档
    'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.AutoSchema',
    # 配置默认的认证方式 base:账号密码验证
    # session:session_id认证
    'DEFAULT_AUTHENTICATION_CLASSES': (
        # drf的这一阶段主要是做验证,middleware的auth主要是设置session和user到request对象
        # 默认的验证是按照验证列表从上到下的验证
        'rest_framework_simplejwt.authentication.JWTAuthentication',
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    )}

SIMPLE_JWT = {
    # 设置jwt的一些参数,比如过期时间
    'ACCESS_TOKEN_LIFETIME': datetime.timedelta(hours=2),
    'REFRESH_TOKEN_LIFETIME': datetime.timedelta(days=8),
}
# # 超时时间
# JWT_AUTH = {
#     'JWT_ALLOW_REFRESH': True,
#     'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=5),
#     'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
#     # token前缀
#     'JWT_AUTH_HEADER_PREFIX': 'JWT',
# }

# AccountInformation
AUTH_USER_MODEL = "zklf_auth.User"
# REST_FRAMEWORK = {
#     # 节流
#     "DEFAULT_THROTTLE_CLASSES": ['webAPP_admin.throttle.VisitThrottle'],

# }

ROOT_URLCONF = 'zklf_manage_platform.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'zklf_manage_platform.wsgi.application'


# Database
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': MYSQL_ADDRESS_PRO,
        'PORT': '3306',
        'NAME': 'cloud_service',
        'USER': MYSQL_ACCOUND_PRO,
        'PASSWORD': MYSQL_PASS_PRO,
    }
}

# Password validation
# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

# mongodb的连接配置
# database_name = DATABASE_VIS_SYSTEM
# MONGO_DATABASE_OPTIONS = {
#     'host': MONGODBIP_VIS_SYSTEM,
#     'port': MONGODBPORT_VIS_SYSTEM,
#     'username': MONGODB_ACCOUNT_VIS_SYSTEM,
#     'password': MONGODB_PASS_VIS_SYSTEM
# }
# database_name = "zklf_cloud"
# MONGO_DATABASE_OPTIONS = {
#     'host': "localhost",
#     'port': 27017,
#     'username': "",
#     'password': ""
# }
# 注册连接
# register_connection('default', database_name, **MONGO_DATABASE_OPTIONS)

# Internationalization
# https://docs.djangoproject.com/en/2.1/topics/i18n/

LANGUAGE_CODE = 'zh-cn'
# LANGUAGE_CODE = 'en'

TIME_ZONE = 'Asia/Shanghai'

USE_I18N = True  # Internationalization(国际化)

USE_L10N = True

USE_TZ = False

# 支持的语言类型-国际化
from django.utils.translation import gettext_lazy as _
LANGUAGES = (
    ('en', _('English')),
    ('zh-hans', _('中文简体')),
    ('zh-hant', _('中文繁體')),
)

# 翻译文件所在目录,需要手工创建
LOCALE_PATHS = (
    os.path.join(BASE_DIR, 'locale'),
)

TEMPLATE_CONTEXT_PROCESSORS = (
    "django.core.context_processors.i18n",
)

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

STATIC_URL = '/static/'

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)

# 跨域增加忽略
CORS_ALLOW_CREDENTIALS = True  # 允许跨域时携带Cookie
CORS_ORIGIN_ALLOW_ALL = True  # 添加白名单
CORS_ORIGIN_WHITELIST = ()  # 添加白名单
CORS_ALLOW_METHODS = (
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
    'VIEW',
)
CORS_ALLOW_HEADERS = (
    'accept',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
    'token'
)

# swagger 配置项
SWAGGER_SETTINGS = {
    # 基础样式
    'SECURITY_DEFINITIONS': {
        "basic": {
            'type': 'basic'
        }
    },
    # 如果需要登录才能够查看接口文档, 登录的链接使用restframework自带的.
    'LOGIN_URL': 'rest_framework:login',
    'LOGOUT_URL': 'rest_framework:logout',
    # 'DOC_EXPANSION': None,
    # 'SHOW_REQUEST_HEADERS':True,
    # 'USE_SESSION_AUTH': True,
    # 'DOC_EXPANSION': 'list',
    # 接口文档中方法列表以首字母升序排列
    'APIS_SORTER': 'alpha',
    # 如果支持json提交, 则接口文档中包含json输入框
    'JSON_EDITOR': True,
    # 方法列表字母排序
    'OPERATIONS_SORTER': 'alpha',
    'VALIDATOR_URL': None,
}

接下来看一下jwt是怎么校验登录状态 from django.contrib.auth import authenticate, login, get_user

jwt采用了django的auth系统,登录状态校验就是authenticate,我贴一下源码

def authenticate(request=None, **credentials):
    """
    If the given credentials are valid, return a User object.
    """
    # 这里会获取所有的backends方法 对应settings里的AUTHENTICATION_BACKENDS(自定义的登录校验)
    for backend, backend_path in _get_backends(return_tuples=True):
        try:
            inspect.getcallargs(backend.authenticate, request, **credentials)
        except TypeError:
            # This backend doesn't accept these credentials as arguments. Try the next one.
            continue
        try:
            user = backend.authenticate(request, **credentials)
        except PermissionDenied:
            # This backend says to stop in our tracks - this user should not be allowed in at all.
            break
        if user is None:
            continue
        # Annotate the user object with the path of the backend.
        user.backend = backend_path
        return user

    # The credentials supplied are invalid to all backends, fire signal
    user_login_failed.send(sender=__name__, credentials=_clean_credentials(credentials), request=request)

# Backend可以是普通的python类,但是关于登陆校验需要具有以下规定的2个方法:

# authenticate(self,username=None,password=None) 或者authenticate(self,token=None),如果通过验证,返回值是一个User对象,如果不通过验证,返回值是None。

# get_user(self,user_id)

# 这两类方法的具体使用不是很相同,关于登陆校验的authenticate,Django在使用他们的时候,会遍历所有的auth backends

# 一旦发现有一个backend校验通过,即返回User对象,那么将会停止下面backend的校验,并且将校验成功的backend绑定在该用户上放入session中,

# 此后如果再次调用该方法,那么将会使用session中的backend进行校验,而不再遍历所有backend了。

AUTHENTICATION_BACKENDS = ['util.auth_func.CustomBackend']

我的自定义authenticate类是这样的

class CustomBackend(ModelBackend):
    """
    @description  :重写的authenticate登录验证
    ---------
    @param  :
    -------
    @Returns  :
    -------
    """
    def authenticate(self, request, username=None, password=None):
        try:
            # Q方法的作用是或的意思,acc_login方法把username和password传过来,
            # 如果以username为条件去库里查没查到的话,就以email为条件去库里查
            # (因为传过来的username 可能是用户名或者email)
            # print(email, password)
            user = User.objects.get(Q(username=username) & Q(is_deleted='0'))
            print(user, "1111111111111111111")
            # 检测username和password是否匹配
            if user.check_password(password):
                return user
        except Exception as e:
            print("error-error")
            print(e)
            return None

    def get_user(self, user_id):
        print("spf-get_user!")
        User = get_user_model()
        try:
            return User.objects.get(id=user_id)
        except User.DoesNotExist:
            return None

有时间再接着写吧。。。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值