1、session认证

.....
login(request, user) #登录成功
# 登录之后获取获取最新的session_key
session_key = request.session.session_key
# 删除非当前用户session_key的记录
for session in Session.objects.filter(~Q(session_key=session_key), expire_date__gte=timezone.now()):
data = session.get_decoded()
if data.get('_auth_user_id', None) == str(request.user.id):
session.delete()

2、jwt认证

如果是JWT认证模式,比较麻烦,个人的解决方法是,每个用户登录后,在redis中存储用户的jwt_token. key是用户的id,value是用户最新的jwt_token. 因为用的django-jwt库,所以这里定义了自己的LoginJWT, 继承JSONWebTokenAPIView.

主要代码改动,只是在登录后,把最新的jwt_token存入redis cache.

class LoginJWT(JSONWebTokenAPIView):

    serializer_class = JSONWebTokenSerializer

    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')
response_data = jwt_response_payload_handler(token, user, request)
response = Response(response_data)
if api_settings.JWT_AUTH_COOKIE:
expiration = (datetime.utcnow() +
api_settings.JWT_EXPIRATION_DELTA)
response.set_cookie(api_settings.JWT_AUTH_COOKIE,
token,
expires=expiration,
httponly=True)
user.token = token
user.save()
k = "{}".format(user.id)
cache.set(k, token, TOKEN_EXPIRE)
return response return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

如果有推送机制的话,可以在此处添加推送机制,把新用户登录的消息推送给登录过的客户端。

这里我没采用推送,而是,在某个经常访问的DRF API中定义验证,验证当前请求带上来的jwt_token是否是redis中存储的最新的,如果不是,则返回用户,请求失败,请重新登录的消息。

比如在某个viewsets.GenericViewSet中,authentication_classes包含自定义的myJWTAuth

authentication_classes = (myJWTAuth, SessionAuthentication)
myJWTAuth代码:

class myJWTAuth(JSONWebTokenAuthentication):
def authenticate(self, request):
"""
Returns a two-tuple of `User` and token if a valid signature has been
supplied using JWT-based authentication. Otherwise returns `None`.
"""
jwt_value = self.get_jwt_value(request) if jwt_value is None:
return None try:
payload = jwt_decode_handler(jwt_value)
except jwt.ExpiredSignature:
msg = _('Signature has expired.')
raise exceptions.AuthenticationFailed(msg)
except jwt.DecodeError:
msg = _('Error decoding signature.')
raise exceptions.AuthenticationFailed(msg)
except jwt.InvalidTokenError:
raise exceptions.AuthenticationFailed() user = self.authenticate_credentials(payload)
k = "{}".format(user.id)
jwt_header=request.META.get('HTTP_AUTHORIZATION',None)
try:
jwt_str=jwt_header.split()[1]
except:
jwt_str="" if cache.has_key(k):
cache_key = cache.get(k)
if jwt_str==cache_key:
cache.set(k, cache_key, TOKEN_EXPIRE)
return (user, jwt_value) raise exceptions.AuthenticationFailed() 参考连接:https://blog.csdn.net/u014633966/article/details/85414656

django项目同一用户不能同时登陆的更多相关文章

  1. Django项目实战—用户头像上传

    1 将文件保存到服务器本地 upload.html <!DOCTYPE html> <html lang="en"> <head> <me ...

  2. Django项目: 4.用户登录登出功能

    用户登录登出功能 一.功能需求分析 1. 登录退出功能分析 流程图 功能 登录页面 登录功能 退出功能 二.登录页面 1. 接口设计 接口说明 类目 说明 请求方法 GET url定义 /user/l ...

  3. 新建Django项目示例--图书管理系统

    知识点: Django 1. 安装 1. Django版本 1.11.xx 2. 安装方式 1. 命令行 --> Python环境(双版本,pip的使用) 2. PyCharm安装 2. 创建D ...

  4. python框架Django实战商城项目之用户模块创建

    创建用户APP 整个项目会存在多个应用,需要存放在一个单独的文件包了,所以新建一个apps目录,管理所有子应用. 在apps包目录下穿件users应用 python ../../manage.py s ...

  5. mac osx 上面部署Django项目 apache+mysql+mod_wsgi

    1.安装Xcode command line tools 首先,编译mysql和Homebrew需要用到Xcode command line tools,所以首先安装command line tool ...

  6. django项目中购物车的实现

    对于做项目而言,最重要的是分析清楚自己负责模块的思路,确定思路后,把每一步实现的步骤确定后,根据步骤,去实现代码,测试. 购物车的逻辑:    登录用户可以添加购物车,未登陆用户页可以添加到购物车   ...

  7. 测试开发之Django——No5.Django项目的部署(CentOS7+nginx)

    配置环境:CentOS7 1.安装python3环境 默认的CentOS7系统中,会安装python2.7的版本,由于Django2.0并不支持python2.7的版本,所以我们需要自己在系统中安装p ...

  8. Django项目知识点汇总

    目录 一.wsgi接口 二.中间件 三.URL路由系统 四.Template模板 五.Views视图 六.Model&ORM 七.Admin相关 八.Http协议 九.COOKIE 与 SES ...

  9. django项目实现第三方github登录

    OAuth(开放授权 Open Authorization)是一个开放标准,允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容 ...

随机推荐

  1. 移动端控制视频点击播放点击下一个视频时自动停止播放&监听滑动溢出屏幕高度时停止播放

    直接上代码js部分: <script type="text/javascript"> var go;//记录video播放器位置 var video=document. ...

  2. TP5报错

    Array to string conversion 数组不能用echo来输出,可使用var_dump().dump()或print_r()

  3. poj3126 Prime Path 广搜bfs

    题目: The ministers of the cabinet were quite upset by the message from the Chief of Security stating ...

  4. Django + Uwsgi + Nginx 的生产环境部署

    使用runserver可以使我们的django项目很便捷的在本地运行起来,但这只能在局域网内访问,如果在生产环境部署django,就要多考虑一些问题了.比如静态文件处理,安全,效率等等,本篇文章总结归 ...

  5. ExtJs5的基本理论概念

    概述 理解ExtJs里面的一些基本关键字的概念是使用ExtJs搭建MMVC框架的基础,在ExtJs中,我们通常遇到ExtJs的配置和启动项Ext.application(),该方法是ExtJs程序初始 ...

  6. 一起学爬虫——使用Beautiful Soup爬取网页

    要想学好爬虫,必须把基础打扎实,之前发布了两篇文章,分别是使用XPATH和requests爬取网页,今天的文章是学习Beautiful Soup并通过一个例子来实现如何使用Beautiful Soup ...

  7. js下载base64格式的图片(兼容火狐)

    //下载图片 download() { let imgData = 'data:image/png;base64,iVBORw0KGgoAAAANSUh........'; this.download ...

  8. python基础篇_004_装饰器函数

    python装饰器函数 1.装饰器函数引导 功能:计算函数执行时长 import time """ 方式一: 函数首位添加时间,差值就是函数执行时间 缺点:每个函数都要加 ...

  9. 【C#】时间类型修改

    鉴于前后端分离发展的迅速.前端很多时间控件都会读UTC时间. 安利一个小知识 // // 摘要: // Creates a new System.DateTime object that has th ...

  10. (DP) 关于最优三角剖分

    https://www.cnblogs.com/Konjakmoyu/p/4905563.html 这个人写的好 最优三角剖分的核心思想: 确定决策顺序. 有时一个解可以用许多决策顺序得出, 这时候我 ...