異なる場所からDjango Webアプリケーションへの複数のログインを検出するにはどうすればよいですか?
-
03-07-2019 - |
質問
Djangoアプリケーションでの個々のログインに対して、一度に1つの認証済みセッションのみを許可したい。したがって、ユーザーが特定のIPアドレスでWebページにログインし、それらの同じユーザー資格情報を使用して別のIPアドレスからログインする場合、何かをしたい(最初のユーザーをログアウトするか、2番目のユーザーへのアクセスを拒否する)
解決
これがまだ必要かどうかはわかりませんが、ソリューションを共有すると思いました:
1)django-trackingをインストールします(Van Gale Google Maps + 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の後にあることを確認してください。新しいユーザーがログインすると、以前のログインが自動的にバンプされます:)
他のヒント
ここで提案されているように既に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
ルックアップに追加できます。
Djangoのミドルウェアがおそらく役立つでしょうあなたはこれを達成します。問題は、おそらく同じIPアドレスからの複数の匿名セッションを許可したいということです。異なるユーザーの認証セッションであっても、同じユーザーの認証セッションは許可しません。
次のことを行います:
-
ユーザーの最後のログインのIPアドレスを保存するユーザープロファイルモデルを作成します。 Djangoのユーザーに関する追加情報の保存ドキュメント。
-
カスタム認証バックエンド。このバックエンドは、トリガーされてユーザーを正常に認証すると(スーパーを呼び出すだけ)、プロファイルモデル内のユーザーの最後のログイン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
の更新が含まれます。
カスタムミドルウェアを使用してこれを行う必要があります。
ミドルウェアの 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 。