Como a pesquisa de sessão do Django para um usuário em particular?

votos
46

Eu estou escrevendo uma aplicação onde eu vou estar acessando o banco de dados do Django e de uma aplicação autónoma. Ambos precisam fazer a verificação de sessão e a sessão deve ser o mesmo para ambos. Django foi construído em verificação de autenticação / sessão, que é o que eu estou usando, agora eu preciso descobrir como reutilizar a mesma sessão para a minha posição aplicativo sozinho.

A minha pergunta é como eu posso procurar um session_key para um usuário particular?

Pelo que parece não há nada que une AUTH_USER e django_session

Publicado 25/10/2008 em 06:27
fonte usuário
Em outras línguas...                            


6 respostas

votos
40

Esta resposta está sendo publicado cinco anos após a pergunta original, mas esta discussão SO é um dos principais resultados do Google na busca de uma solução para este problema (e ainda é algo que não é suportado fora da caixa com Django).

Eu tenho uma solução alternativa para o caso de uso, onde você está apenas preocupado com logado sessões de usuário, que usa um adicional de UserSessionmodelo para mapear usuários a suas sessões, algo como isto:

from django.conf import settings
from django.db import models
from django.contrib.sessions.models import Session

class UserSession(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL)
    session = models.ForeignKey(Session)  

Então você pode simplesmente salvar uma nova UserSessioninstância qualquer momento um usuário faz em:

from django.contrib.auth.signals import user_logged_in

def user_logged_in_handler(sender, request, user, **kwargs):
    UserSession.objects.get_or_create(user = user, session_id = request.session.session_key)

user_logged_in.connect(user_logged_in_handler)

E, finalmente, quando você gostaria de listar (e potencialmente claro) as sessões para um usuário em particular:

from .models import UserSession

def delete_user_sessions(user):
    user_sessions = UserSession.objects.filter(user = user)
    for user_session in user_sessions:
        user_session.session.delete()

Isso é as porcas e parafusos do mesmo, se você quiser mais detalhes eu tenho um post cobrindo-o.

Respondeu 29/09/2014 em 11:19
fonte usuário

votos
28

Isso é um pouco complicada de fazer, porque nem todas as sessões está necessariamente associada a um usuário autenticado; framework de sessão do Django suporta sessões anônimas, bem como, e qualquer pessoa que visite o seu site vai ter uma sessão, independentemente de eles está logado.

Isto é feito mais complicado ainda pelo fato de que o próprio objeto da sessão é serializado - desde Django tem nenhuma maneira de saber quais dados exatamente você deseja armazenar, ele simplesmente serializa o dicionário de dados da sessão em um string (usando "picles" padrão do Python módulo) e animais que em seu banco de dados.

Se você tiver a chave de sessão (que será enviado pelo navegador do usuário como o valor do cookie "sessionid"), a maneira mais fácil de obter para os dados é simplesmente para consultar a tabela de sessão para a sessão com essa chave, que retorna uma Sessão objeto. Você pode então chamar o método desse objeto "get_decoded ()" para obter o dicionário de dados da sessão. Se você não estiver usando Django, você pode olhar para o código-fonte (django / contrib / sessões / models.py) para ver como os dados da sessão é desserializado.

Se você tem o ID de usuário, no entanto, você precisa percorrer todos os objetos de sessão, deserializing cada um e procurando um que tem uma chave chamada "_auth_user_id", e para o qual o valor dessa chave é o ID do usuário .

Respondeu 25/10/2008 em 07:44
fonte usuário

votos
23

Eu encontrei este trecho de código

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

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

não verificamos ainda, mas parece bastante simples.

Respondeu 04/06/2011 em 18:36
fonte usuário

votos
22

Modificando a django_sessiontabela para adicionar um explícita user_idpode tornar a vida muito mais fácil. Supondo que você fazer isso (ou algo similar), aqui estão quatro abordagens para munging coisas a seu gosto:

Fork do django.contrib.sessioncódigo. Eu sei, eu sei, isso é uma coisa horrível para sugerir. Mas é apenas a 500 linhas, incluindo todos os backends e menos os testes. É muito fácil de cortar. Este é o melhor caminho só se você estiver indo para fazer alguma reorganização séria de coisas.

Se você não quer desembolsar, você pode tentar se conectar ao Session.post_savesinal e munge lá.

Ou você poderia MonkeyPatch contrib.session.models.Session.save(). Basta enrolar o método existente (ou criar um novo), fuga / sintetizar o que valores que você precisa, armazená-los em seus novos campos, e depois super(Session, self).save().

Contudo uma outra maneira de fazer isso é colocar em 2 (sim, duas) classes middleware - um antes e um depois SessionMiddlewarena sua settings.py arquivo. Isto é por causa da maneira middleware é processado. O listado depois SessionMiddlewarevai ter, a pedido de entrada, um pedido com a sessão já ligado a ele. O listado antes pode fazer qualquer processamento sobre a resposta e / ou alteração / salvar novamente a sessão.

Nós usamos uma variação sobre esta última técnica para criar pseudo-sessões para o mecanismo de busca para dar-lhes acesso especial ao material que é normalmente membro-somente. Nós também detectar ligações de entrada onde o REFERERcampo é a partir do motor de pesquisa associado e dar ao usuário acesso completo a esse artigo.

Atualizar:

Minha resposta é agora bastante antigo, embora ainda seja principalmente correta. Ver resposta da @ Gavin_Ballard muito mais recente (2014/09/29) abaixo para mais uma abordagem a este problema.

Respondeu 26/10/2008 em 00:33
fonte usuário

votos
6

Peter Rowell, obrigado pela sua resposta. Foi uma tremenda ajuda. Isto é o que eu fiz para fazê-lo funcionar. Só tive que mudar um arquivo em djang.contrib.sessions.

Em django / contrib / sessões / models.py, adicionar o user_id na tabela (adicionar à tabela DB manualmente ou remover a tabela e executar syncdb manage.py).

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)

Agora, em sua visão, onde você faz login (se você usar o login de base do Django, você terá que substituí-lo)

# 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()

Isso funcionou para mim.

Respondeu 03/02/2011 em 23:16
fonte usuário

votos
4

Deparei com esse problema quando eu queria chutar para fora um spammer. Parece definir a sua conta para "inativo" não é suficiente, porque eles ainda podem entrar na sua sessão anterior. Então - como apagar uma sessão para um usuário específico, ou como a expirar deliberadamente uma sessão para um usuário específico?

A resposta é para o usuário do last_logincampo para rastrear a hora em que a sessão foi desativado, que lhe diz que o expire_dateé de duas semanas mais tarde, o que permite que você execute um filtro útil na mesa de sessões:

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()
Respondeu 18/07/2012 em 12:26
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more