django项目同一用户不能同时登陆

摘要:
我没有使用推送,而是在一个经常访问的DRFAPI中定义验证,以验证当前请求带来的jwt _令牌是否是存储在Redis中的最新令牌。如果没有,将返回用户。请求失败。请重新登录。

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项目同一用户不能同时登陆》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇TableCache设置过小造成MyISAM频繁损坏 与 把table_cache适当调小mysql能更快地工作Qt之QComboBox定制下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

oracle查看和修改最大连接数

第一步,在cmd命令行,输入sqlplus 或者直接在plsql中打开command window第二步,根据提示输入用户名与密码1. 查看processes和sessions参数 1 2 3 4 5 6 7 8 9 10 11 12 13 SQL> show parameter processes     NAME            ...

JTW(Json Web Token)

跨地域认证问题(转载) 任何服务都离不开服务器认证的问题,一般的服务器认证流程如下: 上面显示的是单点验证的情况,如果一个公司有多个服务器,当员工登录上一个服务器,按照正常情况,他就可以免密登录其他的服务器,这是如何实现的?见下图: 上面的中间件层可以简单看做是一个mysql数据库,那么就存在一个问题,如果中间件层挂了,那么所有的单点登录都会失败,另一...

如何记录selenium自动化测试过程中接口的调用信息

注: 以下内容引自https://www.cnblogs.com/hhudaqiang/p/6635494.html 上一篇博客,我写了python自动化框架的一些知识和粗浅的看法,在上一篇中我也给自己提出一个需求:如果记录在测试过程中接口的调用情况?提出这个需求,我觉得是有意义的。你在测试过程中肯定会遇到一些莫名其妙的问题,比如:web某个页面一直在刷进...

DateTimeField *** received a naive datetime (***) while time zone support is active

django报错: /usr/local/lib/python2.7/dist-packages/Django-1.8.2-py2.7.egg/django/db/models/fields/init.py:1474: RuntimeWarning: DateTimeField Org.updatedAt received a naive datetime...

Elasticsearch 建立ik中文分词器和自定义分词

一、建立ik中文分词器 1、下载ik中文分词器 进入https://github.com/medcl/elasticsearch-analysis-ik 使用第一种方式安装,进入https://github.com/medcl/elasticsearch-analysis-ik/releases 选择版本7.4.2 。和ES7.4.2的版本保持一致。...

微信小程序高级基础

微信小程序高级基础 微信小程序的注册和服务器配置: 小程序是什么呢?小程序是一种不需要下载安装就可以使用的应用,它实现了应用"触手可及"的梦想,用户扫一扫或者搜一下就可以打开应用,也体现了龙哥"用完即走"的理念,用户不用关心是否安装太多应用的问题,应用将无处不在,随时可用,而且又不用安装卸载。 微信小程序其实是微信提高了自身对于HTML5特性支持的能力,...