2012-09-24 10 views
5

Mam serwer, który zasila kilka aplikacji.Python: Jak "rozwidlić" sesję w django

Proszę sobie wyobrazić, że jestem użytkownikiem zarejestrowanym w co najmniej dwóch takich aplikacjach i używam różnych informacji logowania podczas uzyskiwania dostępu do każdego z nich.

Teraz, jako użytkownik, używam tej samej przeglądarki z różnymi zakładkami, aby uzyskać dostęp do tych aplikacji ... Logowanie po raz pierwszy (w przypadku pierwszej aplikacji) wszystko przebiega zgodnie z przeznaczeniem, ale po uzyskaniu dostępu do drugiej aplikacji (jako drugi użytkownik), to żądanie uzyska dostęp do tego samego obiektu request.session. Po wywołaniu logowania (z poziomu auth) bieżący użytkownik zostanie porównany z użytkownikiem w rzeczywistej postaci request.session (request.session[SESSION_KEY] != user.id) i request.session.flush() zostanie wywołany.

To oznacza, że ​​stracę całą zawartość request.session dla użytkownika, który uzyskał dostęp do 1st aplikację, a tym samym użytkownik request.session zostanie „oznaczony” jako drugi użytkownik request.session z tego punktu.

W tej sytuacji chciałem mieć funkcję/metodę, która pozwala utworzyć nowego request.session dla drugiego użytkownika, pozostawiając oryginał takim jaki jest.

Edytowane po pierwszej odpowiedzi: Po pierwsze, dziękuję za odpowiedź. Próbowałem nie wyjaśniać zbyt wiele, aby uniknąć zbyt zorientowanych odpowiedzi, ale teraz myślę, że powinienem to zrobić:

Ok, już wcześniej nazywałem aplikacje "to", ale tak naprawdę mój projekt obsługuje żądania w celu zaoferowania tego samego końcowego "produktu" (na przykład gry). (Mam kilka aplikacji django w moim projekcie, każdy z konkretnymi orientacjami i zapleczem, w zależności od zastosowanych biznesowych względów).

Bardziej szczegółowe byłoby, gdybym powiedział, że mam różne adresy URL punktów wejścia, użyję poprawnego zaplecza biznesowego aby przetworzyć żądanie i pobrać grę.

Mój główny adres URL jest taki sam (przestrzeń nazw), a mój projekt ma tylko jeden plik ustawień.

enter image description here

+0

Nie jestem pewien, w jaki sposób Django może przesłać plik cookie dla domeny, dla której żądanie nie zostało wykonane ** lub ** www.2.com/playCDS --- przekierowanie na ---> www.me. com/playCDS, a następnie zmieniasz profil użytkownika zgodnie ze stroną odsyłającą, czy tak jest? Nadal pisałem swoją odpowiedź http://stackoverflow.com/a/12571909/140837, będę aktualizował odpowiednio, ale podstawowa odpowiedź jest tam, logika dla ustawień profilu użytkownika się zmienia, ponieważ w twoim przypadku nie wydaje się być " zmień widok podprofilowy ". – amirouche

+0

Czy istnieje jakiś model "SubProfile"? – amirouche

+0

Czy zapoznałeś się z moją odpowiedzią? – amirouche

Odpowiedz

2

Może być kilka odpowiedzi na pytanie, w zależności od tego, czy jesteś gotowy na zmianę „przypadek użycia” czy nie:

a) Nie możesz zmieniać przypadek użycia: to nie jest możliwe, ponieważ jeden Sesja Django jest związana z sesją przeglądarki i kilkoma instancjami lub kartami przeglądarki.

b) Można zmienić przypadek użycia: Użytkownik może jeszcze osiągnąć to za pomocą kilku przeglądarek (lub profili (lub tryb przeglądania prywatnego w chrom/chrom)) bez żadnych modyfikacji do kodu.

c) można wdrożyć „użytkownik” -switch funkcję w swojej witrynie, które pozwalają użytkownikowi na kilka aktywnego profilu w tej samej sesji w różnych oknach, to podobny cel do github funkcji organizacja-switch lub stronie facebook/organization-switch, ale możesz mieć kilka profilów użytkownika w kilku zakładkach, co nie ma miejsca w github lub facebooku.

Aby osiągnąć c) trzeba mieć „Podprofil” instancje wzorem załączonym do modelu „User” i włączyć prawy Podprofil na każde żądanie przychodzącego w oparciu o parametry ciąg kwerendy i utrzymują Podprofil informacji poprzek żądań.

1) Chyba masz już coś takiego Subprofile model z klucza obcego do django.contrib.auth.models.User, można też pogląd, że pozwoli użytkownikiem, aby zmienić jej podprofil. Aby wykonać subprofile-switch, musi on utrwalać informacje w bieżącej sesji tabulacji, której podprogramu używa, ponieważ musi dodać parametr do ciągu zapytania, ponieważ jest to jedyne miejsce związane z kartą, a nie z użytkownikiem -sesja. Na przykład "subprofile = 123". . Trzeba prawidłowo zweryfikować podprofil z formularza i wsp, widok wygląda następująco:

def select_subprofile(request): 
    if request.method == 'POST': 
     form = SubProfileSelectForm(request) 
     if form.is_valid(): 
      subprofile = form.cleaned_data['subprofile'] 
      url = '%s?subprofile' % (reverse('homepage'), subprofile) 
      return redirect(url) # the redirect is something like '/homepage?subprofile=123' 
    else: 
     form = SubProfileSelectForm() 
    return render(request, 'myapp/subprofile_select.html', {'form':form}) 

Ten widok może być na pierwszej stronie każdej gry.

2) Następnie należy pobrać podprofil użytkownika dla bieżącej zakładki. Do tej sprawie będziemy wykorzystywać ciąg kwerendy w middleware (poszukaj howtos on SO i example middlewares bundled with Django jeśli nie wiesz co to jest) może być używany do podłączenia bieżącej SubProfile instancji do request.user. Wola middleware dla każdego żądania przychodzące dołączyć instancję Podprofil odpowiadającą aktualnej informacji Podprofil znalezionego w ciągu kwerendy do bieżącego obiektu użytkownika, middleware wygląda następująco:

class SubProfileMiddleware(object): 

    def process_request(self, request): 
     subprofile = request.GET.get('subprofile', None) 
     if subprofile: 
      # it's important to check for user here or malicious users will be 
      # able to use Subprofiles of other users 
      subprofile = Subprofile.objects.filter(user=request.user, id=subprofile) 
      # This can also be written 
      # subprofile = request.user.subprofile_set.filter(id=subprofile) 
      if not subprofile: 
       # this is a malicious user 
       raise Http403 
      else: 
       request.user.subprofile = subprofile 
     else: 
      # set default subprofile 
      request.user.subprofile = self.user.default_subprofile 

ten sposób masz dostęp w każdym widoku aplikacji do instancji SubProfile na atrybucie subprofile z request.user. Jeśli istnieje poprawny ciąg zapytania subprofile=123, użytkownik będzie miał ten podprofil aktywny, jeśli nie, to domyślny podprofil.

Załóżmy, że twoja aplikacja to aplikacja z Organization modelami, z których każdy ma ściany, na których użytkownik może wysyłać wiadomości za pomocą podprofilu, funkcja umieszczania wiadomości na ścianie ma następujący podpis post_on_organization_wall(subprofile, message, organization), widok używający tego funkcja będzie wyglądać następująco:

def organization_wall_post(request, organization): 
    organization = Organization.objects.get_object_or_404(organization) 
    if request.method == 'POST': 
     form = MessageForm(request.POST) 
     if form.is_valid(): 
      post_on_organization_wall(request.user.subprofile, message, organisation) 
    else: 
     form = MessageForm() 
    return render(request, 'organisation/wall_post.html', {'form': form}) 

3) teraz trzeba utrzymywać Podprofil informacji poprzek żądań. Najprostszym sposobem na to jest zastąpienie kodu everycall na {% url %} własnym znacznikiem szablonu url, który sprawdza obecność łańcucha subprofilów w zapytaniu i dodaje go do żądanego adresu URL. Możesz ponownie użyć the code of Django's url template tag.

0

Jeśli rozumiem Twojego problemu poprawnie, problem jest to, że jesteś dzielenie sesje między aplikacjami nawet jeśli użytkownicy są różne. Powinieneś być w stanie rozwiązać ten problem, ustawiając albo SESSION_COOKIE_DOMAIN, SESSION_COOKIE_PATH, albo SESSION_COOKIE_NAME w settings.py, aby upewnić się, że twoje aplikacje nie przejmują nawzajem sesji.