本文根据实际使用讲解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
有时间再接着写吧。。。