功能变化: 加入浏览器单点登录
parent
69d8c3efc0
commit
c514a254c7
|
@ -54,6 +54,7 @@ INSTALLED_APPS = [
|
||||||
"rest_framework",
|
"rest_framework",
|
||||||
"django_filters",
|
"django_filters",
|
||||||
"corsheaders", # 注册跨域app
|
"corsheaders", # 注册跨域app
|
||||||
|
'rest_framework_simplejwt.token_blacklist',
|
||||||
"dvadmin.system",
|
"dvadmin.system",
|
||||||
"drf_yasg",
|
"drf_yasg",
|
||||||
"captcha",
|
"captcha",
|
||||||
|
@ -306,12 +307,14 @@ from datetime import timedelta
|
||||||
|
|
||||||
SIMPLE_JWT = {
|
SIMPLE_JWT = {
|
||||||
# token有效时长
|
# token有效时长
|
||||||
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=120),
|
"ACCESS_TOKEN_LIFETIME": timedelta(seconds=10),
|
||||||
# token刷新后的有效时间
|
# token刷新后的有效时间
|
||||||
"REFRESH_TOKEN_LIFETIME": timedelta(days=1),
|
"REFRESH_TOKEN_LIFETIME": timedelta(days=1),
|
||||||
# 设置前缀
|
# 设置前缀
|
||||||
"AUTH_HEADER_TYPES": ("JWT",),
|
"AUTH_HEADER_TYPES": ("JWT",),
|
||||||
"ROTATE_REFRESH_TOKENS": True,
|
"ROTATE_REFRESH_TOKENS": True,
|
||||||
|
'BLACKLIST_AFTER_ROTATION': True,
|
||||||
|
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
|
||||||
}
|
}
|
||||||
|
|
||||||
# ====================================#
|
# ====================================#
|
||||||
|
@ -387,6 +390,8 @@ SYSTEM_CONFIG = {}
|
||||||
# 字典配置
|
# 字典配置
|
||||||
DICTIONARY_CONFIG = {}
|
DICTIONARY_CONFIG = {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================= #
|
# ================================================= #
|
||||||
# ******************** 插件配置 ******************** #
|
# ******************** 插件配置 ******************** #
|
||||||
# ================================================= #
|
# ================================================= #
|
||||||
|
@ -399,4 +404,7 @@ PLUGINS_URL_PATTERNS = []
|
||||||
# from dvadmin_upgrade_center.settings import * # 升级中心
|
# from dvadmin_upgrade_center.settings import * # 升级中心
|
||||||
# from dvadmin_celery.settings import * # celery 异步任务
|
# from dvadmin_celery.settings import * # celery 异步任务
|
||||||
# ...
|
# ...
|
||||||
|
from dvadmin_third.settings import * # 扫码登录
|
||||||
|
from dvadmin_uniapp.settings import * # uniapp后端
|
||||||
|
|
||||||
# ********** 一键导入插件配置结束 **********
|
# ********** 一键导入插件配置结束 **********
|
||||||
|
|
|
@ -45,6 +45,7 @@ class Users(CoreModel,AbstractUser):
|
||||||
blank=True,
|
blank=True,
|
||||||
help_text="关联部门",
|
help_text="关联部门",
|
||||||
)
|
)
|
||||||
|
last_token = models.CharField(max_length=255,null=True,blank=True, verbose_name="最后一次登录Token", help_text="最后一次登录Token")
|
||||||
|
|
||||||
def set_password(self, raw_password):
|
def set_password(self, raw_password):
|
||||||
super().set_password(hashlib.md5(raw_password.encode(encoding="UTF-8")).hexdigest())
|
super().set_password(hashlib.md5(raw_password.encode(encoding="UTF-8")).hexdigest())
|
||||||
|
|
|
@ -12,7 +12,8 @@ from drf_yasg.utils import swagger_auto_schema
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
|
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
|
||||||
from rest_framework_simplejwt.views import TokenObtainPairView
|
from rest_framework_simplejwt.tokens import RefreshToken, AccessToken
|
||||||
|
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
@ -105,6 +106,13 @@ class LoginSerializer(TokenObtainPairSerializer):
|
||||||
request.user = self.user
|
request.user = self.user
|
||||||
# 记录登录日志
|
# 记录登录日志
|
||||||
save_login_log(request=request)
|
save_login_log(request=request)
|
||||||
|
# 将之前登录用户的token加入黑名单
|
||||||
|
last_token = self.user.last_token
|
||||||
|
if last_token:
|
||||||
|
token = RefreshToken(last_token)
|
||||||
|
token.blacklist()
|
||||||
|
# 将最新的token保存到用户表
|
||||||
|
Users.objects.filter(id=self.user.id).update(last_token=data.get('refresh'))
|
||||||
return {"code": 2000, "msg": "请求成功", "data": data}
|
return {"code": 2000, "msg": "请求成功", "data": data}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import traceback
|
||||||
from django.db.models import ProtectedError
|
from django.db.models import ProtectedError
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from rest_framework.exceptions import APIException as DRFAPIException, AuthenticationFailed
|
from rest_framework.exceptions import APIException as DRFAPIException, AuthenticationFailed
|
||||||
|
from rest_framework.status import HTTP_407_PROXY_AUTHENTICATION_REQUIRED, HTTP_401_UNAUTHORIZED
|
||||||
from rest_framework.views import set_rollback, exception_handler
|
from rest_framework.views import set_rollback, exception_handler
|
||||||
|
|
||||||
from dvadmin.utils.json_response import ErrorResponse
|
from dvadmin.utils.json_response import ErrorResponse
|
||||||
|
@ -33,8 +34,14 @@ def CustomExceptionHandler(ex, context):
|
||||||
# 调用默认的异常处理函数
|
# 调用默认的异常处理函数
|
||||||
response = exception_handler(ex, context)
|
response = exception_handler(ex, context)
|
||||||
if isinstance(ex, AuthenticationFailed):
|
if isinstance(ex, AuthenticationFailed):
|
||||||
code = 401
|
if response and response.data.get('detail') =="Given token not valid for any token type":
|
||||||
msg = ex.detail
|
code = 401
|
||||||
|
msg = ex.detail
|
||||||
|
elif response and response.data.get('detail') =="Token is blacklisted":
|
||||||
|
return ErrorResponse(status=HTTP_401_UNAUTHORIZED)
|
||||||
|
else:
|
||||||
|
code = 401
|
||||||
|
msg = ex.detail
|
||||||
elif isinstance(ex,Http404):
|
elif isinstance(ex,Http404):
|
||||||
code = 400
|
code = 400
|
||||||
msg = "接口地址不正确"
|
msg = "接口地址不正确"
|
||||||
|
|
|
@ -78,12 +78,10 @@ function createService () {
|
||||||
// return dataAxios.data
|
// return dataAxios.data
|
||||||
return dataAxios
|
return dataAxios
|
||||||
case 401:
|
case 401:
|
||||||
// TODO 置换token 未完善
|
refreshTken().then(res => {
|
||||||
util.cookies.remove('token')
|
util.cookies.set('token', res.access)
|
||||||
util.cookies.remove('uuid')
|
router.push({path:'/index'})
|
||||||
util.cookies.remove('refresh')
|
})
|
||||||
router.push({ path: '/login' })
|
|
||||||
errorCreate(`${getErrorMessage(dataAxios.msg)}`)
|
|
||||||
break
|
break
|
||||||
case 404:
|
case 404:
|
||||||
dataNotFound(`${dataAxios.msg}`)
|
dataNotFound(`${dataAxios.msg}`)
|
||||||
|
@ -109,13 +107,11 @@ function createService () {
|
||||||
error.message = '请求错误'
|
error.message = '请求错误'
|
||||||
break
|
break
|
||||||
case 401:
|
case 401:
|
||||||
refreshTken().then(res => {
|
util.cookies.remove('token')
|
||||||
util.cookies.set('token', res.access)
|
util.cookies.remove('uuid')
|
||||||
}).catch(e => {
|
util.cookies.remove('refresh')
|
||||||
router.push({ name: 'login' })
|
router.push({ path: '/login' })
|
||||||
router.go(0)
|
error.message = '系统已检测到您的账号在其他地方登录~'
|
||||||
error.message = '未认证,请登录'
|
|
||||||
})
|
|
||||||
break
|
break
|
||||||
case 403:
|
case 403:
|
||||||
error.message = '拒绝访问'
|
error.message = '拒绝访问'
|
||||||
|
|
|
@ -33,7 +33,8 @@ export default {
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
captcha,
|
captcha,
|
||||||
captchaKey
|
captchaKey,
|
||||||
|
refresh: util.cookies.get('refresh') || null
|
||||||
})
|
})
|
||||||
// 设置 cookie 一定要存 uuid 和 token 两个 cookie
|
// 设置 cookie 一定要存 uuid 和 token 两个 cookie
|
||||||
// 整个系统依赖这两个数据进行校验和存储
|
// 整个系统依赖这两个数据进行校验和存储
|
||||||
|
|
Loading…
Reference in New Issue