我希望一次只允许一个经过身份验证的会话,以便在我的Django应用程序中进行单独登录。因此,如果用户登录到给定IP地址的网页,并且使用相同的用户凭据从不同的IP地址登录,我想做某事(登出第一个用户或拒绝访问第二个用户。)< / p>
答案 0 :(得分:18)
不确定是否仍然需要,但我想我会分享我的解决方案:
1)安装django-tracking(谢谢Gale谷歌地图+ GeoIP太棒了!)
2)添加此中间件:
from django.contrib.sessions.models import Session
from tracking.models import Visitor
from datetime import datetime
class UserRestrictMiddleware(object):
"""
Prevents more than one user logging in at once from two different IPs
"""
def process_request(self, request):
ip_address = request.META.get('REMOTE_ADDR','')
try:
last_login = request.user.last_login
except:
last_login = 0
if unicode(last_login)==unicode(datetime.now())[:19]:
previous_visitors = Visitor.objects.filter(user=request.user).exclude(ip_address=ip_address)
for visitor in previous_visitors:
Session.objects.filter(session_key=visitor.session_key).delete()
visitor.user = None
visitor.save()
3)确保它位于VisitorTrackingMiddleware之后,你会发现以前的登录会在有人登录时自动碰撞:)
答案 1 :(得分:9)
如果您已按照此处的建议使用django-tracking,则可以更轻松地实现此目的:
定义信号处理程序:
# myapp/signals.py
def kick_my_other_sessions(sender, request=None, user=None, **kwargs):
from tracking.models import Visitor
from django.contrib.sessions.models import Session
keys = [v.session_key for v in Visitor.objects.filter(user=request.user).exclude(session_key=request.session.session_key)]
Session.objects.filter(session_key__in=keys).delete()
为user_logged_in信号创建一个监听器:
# myapp/__init__.py
from myapp.signals import kick_my_other_sessions
from django.contrib.auth.signals import user_logged_in
user_logged_in.connect(kick_my_other_sessions, sender=User)
这将构成一种“最后用户登录获胜”系统。如果您希望同一用户允许多个登录来自同一个IP,您可以在.exclude()
查找中添加Visitors
。
答案 2 :(得分:6)
您需要使用自定义中间件执行此操作。
在您的中间件process_request()
方法中,您可以访问请求对象,以便执行以下操作:
session_key = request.session.session_key
ip_address = request.META.get('REMOTE_ADDR', '')
现在您知道了IP地址,因此请检查您创建的模型(大致)是这样的:
class SessionIPS(models.Model):
session = models.ForeignKey(Session)
IP = models.CharField(max_length=20)
因此,当创建或删除会话时,您将相应地修改会话ip的表,并在请求进入时确保IP地址未用于另一个会话。如果是,则从中间件返回Http404(或类似的东西)。
可插入的应用程序可以显示更多细节(甚至包括自己模型中的IP地址)是django-tracking。
答案 3 :(得分:6)
Django的middleware可能会帮助你实现这一目标。问题是您可能希望允许来自同一IP地址的多个匿名会话,甚至是针对不同用户的经过身份验证的会话,但不允许同一用户的经过身份验证的会话。
你想要:
创建用户个人资料模型以存储用户上次登录的IP地址。请参阅Django的Storing additional information about users文档。
实施custom authentication backend。这个后端在被触发并成功验证用户时(只是调用超级用户)会消除用户在配置文件模型中的最后一次登录IP。
实现Django的django.contrib.sessions.SessionMiddleware
类的子类。实施process_request
。如果request.user
对象的配置文件模型没有IP地址,请设置它并允许该请求。如果它有一个IP,并且IP与当前请求的IP(request.META.REMOTE_ADDR
)不同,那么做任何你想要注销另一个用户的事情,或者向请求者返回一个错误。
更新settings.py
文件,以便首先处理自定义身份验证后端,以便首先处理自定义会话中间件。这涉及更新settings.AUTHENTICATION_BACKENDS
和settings.MIDDLEWARE_CLASSES
。