60

私は、django およびスタンドアロン アプリケーションからデータベースにアクセスするアプリケーションを作成しています。両方がセッション検証を行う必要があり、セッションは両方で同じである必要があります。Django には、私が使用しているものである認証/セッション検証が組み込まれています。今、スタンドアロン アプリケーションで同じセッションを再利用する方法を理解する必要があります。

私の質問は、特定のユーザーの session_key を検索するにはどうすればよいですか?

見た目から、auth_user と django_session を結びつけるものは何もありません

4

6 に答える 6

31

このコードスニペットを見つけました

from django.contrib.sessions.models import Session
from django.contrib.auth.models import User

session_key = '8cae76c505f15432b48c8292a7dd0e54'

session = Session.objects.get(session_key=session_key)
uid = session.get_decoded().get('_auth_user_id')
user = User.objects.get(pk=uid)

print user.username, user.get_full_name(), user.email

こちら http://scottbarnham.com/blog/2008/12/04/get-user-from-session-key-in-django/

まだ確認していませんが、かなり簡単に見えます。

于 2011-06-04T17:36:31.230 に答える
28

すべてのセッションが必ずしも認証されたユーザーに関連付けられているわけではないため、これを行うのは少し難しいです。Django のセッション フレームワークは匿名セッションもサポートしており、ログインしているかどうかに関係なく、サイトにアクセスした人は誰でもセッションを利用できます。

これは、セッション オブジェクト自体がシリアル化されているという事実によって、さらに複雑になります。Django は、保存したいデータを正確に知る方法がないため、セッション データの辞書を文字列にシリアル化するだけです (Python の標準的な「pickle」を使用)。モジュール) をデータベースに追加します。

セッション キー (ユーザーのブラウザによって Cookie 値 "sessionid" として送信されます) がある場合、データを取得する最も簡単な方法は、そのキーを使用してセッションのセッション テーブルをクエリすることです。物体。次に、そのオブジェクトの「get_decoded()」メソッドを呼び出して、セッション データの辞書を取得できます。Django を使用していない場合は、ソース コード (django/contrib/sessions/models.py) を見て、セッション データがどのように逆シリアル化されているかを確認できます。

ただし、ユーザーIDがある場合は、すべてのSessionオブジェクトをループして、それぞれを逆シリアル化し、「_auth_user_id」という名前のキーを持ち、そのキーの値がユーザーIDであるオブジェクトを探す必要があります.

于 2008-10-25T06:44:49.583 に答える
26

テーブルを変更しdjango_sessionて明示的なものを追加すると、作業user_idが大幅に楽になります。あなたがそれ(または同様の何か)を行うと仮定すると、ここにあなたの好みに合わせて物事を変えるための4つのアプローチがあります:

コードをフォークしdjango.contrib.sessionます。私は知っています、私は知っています、それは提案するのは恐ろしいことです。ただし、すべてのバックエンドとテストを除いた500行のみです。ハッキングするのはかなり簡単です。これは、深刻な再配置を行う場合にのみ最適なルートです。

分岐したくない場合は、Session.post_save信号に接続してそこで接続してみてください。

または、MonkeyPatchを使用することもできますcontrib.session.models.Session.save()。既存のメソッドをラップして(または新しいメソッドを作成して)、必要な値をブレークアウト/合成し、それらを新しいフィールドに格納してから、super(Session, self).save()

これを行うさらに別の方法は、2つの(はい、2つの)ミドルウェアクラスを設定することです。1つはsettings.pyファイルの前に、もう1つはSessionMiddlewareです。これは、ミドルウェアの処理方法が原因です。後にリストされているものSessionMiddlewareは、インバウンドリクエストで、セッションがすでにアタッチされているリクエストを取得します。前にリストされたものは、応答に対して任意の処理を実行したり、セッションを変更/再保存したりできます。

この最後の手法のバリエーションを使用して、検索エンジンスパイダーの疑似セッションを作成し、通常はメンバーのみである資料への特別なアクセスを提供しました。また、フィールドが関連する検索エンジンからのものであるインバウンドリンクを検出REFERERし、ユーザーにその1つの記事へのフルアクセスを提供します。

アップデート:

私の答えは今ではかなり古いものですが、それでもほとんど正しいです。この問題へのさらに別のアプローチについては、以下の@Gavin_Ballardのはるかに最近の回答(2014年9月29日)を参照してください。

于 2008-10-25T23:33:16.977 に答える
7

Peter Rowell, thanks for your response. It was a tremendous help. This is what I did to get it working. Only had to change one file in djang.contrib.sessions.

In django/contrib/sessions/models.py, add the user_id to the table (add to DB table manually or drop table and run manage.py syncdb).

class Session(models.Model):

    ...

    user_id = models.IntegerField(_('user_id'), null=True)

    ...

    def save(self, *args, **kwargs):
        user_id = self.get_decoded().get('_auth_user_id')
        if ( user_id != None ):
            self.user_id = user_id

        # Call the "real" save() method.
        super(Session, self).save(*args, **kwargs)

Now in your view where you do login (if you use django's base login, you will have to override it)

# On login, destroy all prev sessions
        # This disallows multiple logins from different browsers
        dbSessions = Session.objects.filter( user_id = request.user.id )
        for index, dbSession in enumerate( dbSessions ):
            if ( dbSession.session_key != request.session.session_key ):
                dbSession.delete()

This worked for me.

于 2011-02-03T22:16:26.497 に答える
6

スパマーを追い出そうとしたときに、この問題に出くわしました。アカウントを「非アクティブ」に設定するだけでは十分ではないようです。以前のセッションにまだ参加できるからです。では、特定のユーザーのセッションを削除する方法、または特定のユーザーのセッションを故意に期限切れにする方法は?

答えは、last_loginフィールドを使用して、セッションが無効になった時刻を追跡するexpire_dateことです。これにより、2 週間後であることがわかるため、セッション テーブルで便利なフィルターを実行できます。

from django.contrib.sessions.models import Session
from django.contrib.auth.models import User
from datetime import datetime
from dateutil.relativedelta import relativedelta

baduser = User.objects.get(username="whoever")     
two_weeks = relativedelta(weeks=2)
two_hours = relativedelta(hours=2)
expiry = baduser.last_login + two_weeks
sessions = Session.objects.filter(
    expire_date__gt=expiry - two_hours,
    expire_date__lt=expiry + two_hours
) 
print sessions.count() # hopefully a manageable number

for s in sessions:
    if s.get_decoded().get('_auth_user_id') == baduser.id:
        print(s)
        s.delete()
于 2012-07-18T11:26:19.447 に答える