防止使用相同凭据进行多次登录

Ank*_*eva 3 python django django-models python-2.7

我检查了以前提出的类似问题,但我无法找到合适的答案。

要求:在两台不同的计算机上,不能使用相同的用户凭据来访问应用程序。

我所实现的,在登录时,从用户以前使用的所有设备中注销。

from django.contrib.auth.signals import user_logged_in

class UserAccount(models.Model):
    """
    This model will be used to extra user information.
    """

    user = models.OneToOneField(User, db_index=True)
    session = models.CharField(max_length=40, null=True)
    ip_address = models.IPAddressField()

def logout_other_devices(user, request, **kwargs):
    """
    Delete session(logout all) other devices with same credential.
    """

    profile = user.useraccount

    if profile.session:
        Session.objects.filter(session_key=profile.session).delete()

    profile.session = request.session.session_key
    profile.ip_address = request.META.get('REMOTE_ADDR')
    profile.save()


user_logged_in.connect(logout_other_devices)
Run Code Online (Sandbox Code Playgroud)

剩下的就是,如果一个用户登录一个系统并将其sessionid(通过 cookie)传递给在同一 WiFi(或 LAN)连接下连接的第二个用户,那么第二个用户的 IP 在服务器上是相同的。在允许第二个用户访问任何网站数据之前,如何区分第二个用户并注销第一个用户。

xyr*_*res 9

每次用户登录时,Django 都会生成一个会话密钥并将其保存在数据库中。如果用户从其他浏览器/设备登录,Django 将创建一个新的会话密钥而不删除旧的会话密钥。

如果您想让用户退出其他设备,您只需从数据库中删除他/她之前的会话密钥即可。

由于没有简单的方法来识别哪个密钥属于哪个用户,因此您必须在用户登录后将会话密钥保存在用户模型中。因此,在您的用户模型中添加另一个名为 的字段,如下所示session_key

# models.py

class UserAccount(...):
    ...
    session_key = models.CharField(max_length=100, null=True)
Run Code Online (Sandbox Code Playgroud)

您还需要对登录视图进行一些更改,如下所示:

# views.py

from django.contrib.sessions.backend.db import Session

def login_view(request):
    ...
    user = authenticate(...)
    
    # Here comes good part

    if user is not None:

        if user.session_key: # check if user has session_key. This will be true for users logged in on another device
            try:
                s = Session.objects.get(session_key=user.session_key)
            except Session.DoesNotExist:
                pass
            else:
                s.delete() # delete the old session_key from db

       login(request, user) # log the user in

       # set new session_key for user instance
       user.session_key = request.session.session_key
       user.save() # save the user

    # do other stuff
Run Code Online (Sandbox Code Playgroud)