Django : 사용자가 로그인 할 때 신호를 보내나요?


82

내 Django 앱에서 사용자가 로그인 할 때 몇 가지주기적인 백그라운드 작업 실행을 시작하고 사용자가 로그 아웃 할 때 실행을 중지해야하므로 우아한 방법을 찾고 있습니다.

  1. 사용자 로그인 / 로그 아웃 알림 받기
  2. 사용자 로그인 상태 조회

내 관점에서 이상적인 솔루션은

  1. 각각에 의해 전송 된 신호 django.contrib.auth.views.login... views.logout
  2. 또는 django.contrib.auth.models.User.is_logged_in()유사한 방법... User.is_active()... User.is_authenticated()

Django 1.1.1에는이 기능이 없으며 소스를 패치하고 추가하는 것을 꺼려합니다 (어쨌든 그렇게하는 방법을 모르겠습니다).

임시 솔루션 is_logged_in으로 기본적으로 지워지고 사용자가 처음 방문 페이지 (에서 정의 됨 LOGIN_REDIRECT_URL = '/')를 방문 할 때 설정 되고 후속 요청에서 쿼리 되는 UserProfile 모델에 부울 필드를 추가했습니다 . UserProfile에 추가 했으므로 해당 용도로만 내장 사용자 모델을 파생하여 사용자 정의 할 필요가 없습니다.

이 솔루션이 마음에 들지 않습니다. 사용자가 명시 적으로 로그 아웃 버튼을 클릭하면 플래그를 지울 수 있지만 대부분의 경우 사용자는 페이지를 떠나거나 브라우저를 닫습니다. 이 경우 깃발을 지우는 것은 나에게 직접적으로 보이지 않습니다. 게다가 (그것은 오히려 데이터 모델 명확성 nitpicking) is_logged_inUserProfile에 속하지 않고 User 모델에 속합니다.

누구든지 대체 접근 방식을 생각할 수 있습니까?


4
새로운 답변을 선택하십시오. 현재 허용되는 것은 1.3에 추가 된 신호를 고려할 때 매우 좋지 않은 선택입니다.
Bryson 2011

1
네가 옳아; 수락 된 답변을 변경했습니다.
ssc

답변:


151

다음과 같은 신호를 사용할 수 있습니다 (나는 models.py에 넣었습니다)

from django.contrib.auth.signals import user_logged_in


def do_stuff(sender, user, request, **kwargs):
    whatever...

user_logged_in.connect(do_stuff)

django 문서 참조 : https://docs.djangoproject.com/en/dev/ref/contrib/auth/#module-django.contrib.auth.signals 및 여기 http://docs.djangoproject.com/en/dev/ 주제 / 신호 /


8
이제 Django 1.3이 이러한 신호를 제공 하므로 로그인 / 로그 아웃 호출을 래핑하는 것보다 훨씬 더 나은 솔루션입니다. 또한 새로운 로그인 방법 (예 : Facebook / Twitter / OpenID 로그인)을 설정해도 여전히 작동합니다.
Jordan Reiter

9
대신 models.py에 코드를 삽입 signals.py하고 모듈의 __init__.py파일 에 자동으로 가져 오는 것이 좋습니다 .
Daniel Sokolowski 2013 년

이 신호를 사용하여 로그인 및 로그 아웃시 javascript를 실행하는 방법은 무엇입니까?
Ashish Gupta

15

@PhoebeB 답변 외에도 다음 @receiver과 같은 데코레이터 를 사용할 수 있습니다 .

from django.contrib.auth.signals import user_logged_in
from django.dispatch import receiver

@receiver(user_logged_in)
def post_login(sender, user, request, **kwargs):
    ...do your stuff..

그리고 그것을 signals.py앱 디렉토리에 넣으면 다음을 추가하십시오 apps.py.

class AppNameConfig(AppConfig):
    ...
    def ready(self):
        import app_name.signals

13

한 가지 옵션은 Django의 로그인 / 로그 아웃 뷰를 자신의 것으로 래핑하는 것입니다. 예를 들면 :

from django.contrib.auth.views import login, logout

def my_login(request, *args, **kwargs):
    response = login(request, *args, **kwargs)
    #fire a signal, or equivalent
    return response

def my_logout(request, *args, **kwargs):
    #fire a signal, or equivalent
    return logout(request, *args, **kwargs)

그런 다음 Django가 아닌 코드에서 이러한 뷰를 사용합니다.

로그인 상태 쿼리와 관련하여 요청 객체에 대한 액세스 권한이 있으면 매우 간단합니다. 요청의 사용자 속성을 확인하여 등록 된 사용자인지 익명의 사용자인지 확인하고 빙고하면됩니다. Django 문서 를 인용하려면 :

if request.user.is_authenticated():
    # Do something for logged-in users.
else:
    # Do something for anonymous users.

요청 객체에 대한 액세스 권한이없는 경우 현재 사용자가 로그인했는지 확인하는 것이 어려울 것입니다.

편집하다:

불행히도 User.is_logged_in()기능 을 얻을 수는 없습니다 . 이는 HTTP 프로토콜의 제한입니다. 그러나 몇 가지 가정을하면 원하는 것에 가까워 질 수 있습니다.

첫째, 왜 그 기능을 얻을 수 없습니까? 글쎄, 당신은 브라우저를 닫는 사람과 새 브라우저를 가져 오기 전에 페이지에서 시간을 보내는 사람의 차이를 구분할 수 없습니다. 누군가 실제로 사이트를 떠나거나 브라우저를 닫을 때 HTTP를 통해 알 수있는 방법이 없습니다.

여기에 완벽하지 않은 두 가지 옵션이 있습니다.

  1. Javascript의 unload이벤트를 사용 하여 사용자가 페이지를 떠날 때 포착하십시오. 그러나 사용자가 여전히 사이트를 탐색 때 로그 아웃하지 않도록주의해서 논리를 작성해야합니다 .
  2. 사용자가 로그인 할 때마다 로그 아웃 신호를 실행합니다. 또한 만료 된 세션을 플러시하기 위해 상당히 자주 실행되는 크론 작업을 만듭니다. 만료 된 세션이 삭제되면 세션의 사용자 (익명이 아닌 경우)에 더 이상 활성 세션이 없는지 확인합니다.이 경우 로그 아웃 신호를 실행합니다.

이러한 솔루션은 지저분하고 이상적이지는 않지만 불행히도 최선의 방법입니다.


이것은 여전히 ​​"대부분의 경우 사용자가 페이지를 떠나거나 브라우저를 닫는 경우"상황을 해결하지 못합니다.
Joel L

귀하의 답변에 감사드립니다. 물론 로그인 / 로그 아웃을 래핑하면 소스를 패치하지 않아도됩니다. 그러나 약간의 수정 사항 : 로그인이 호출되기 전에 신호가 my_login으로 전송되면 사용자는 신호 처리기에서 여전히 익명입니다. 더 낫다 (올바르게 형식화 될 것이라고 생각하지 않는다) : def my_login (request) : response = login (request) #fire a signal, or equivalent return response 또한, 이미 is_authenticated를 사용하고 있습니다. 그 이상. 그러나 지금까지 데이터 모델의 새로운 is_logged_in 부분은 사용되지 않고 있습니다.
ssc

주변의 좋은 점. 나는 그 is_logged_in내용을 전혀 잘 다루지 않은 것 같지만 (죄송합니다. 게시물을 잘 읽지 못한 것 같습니다.) 그 영역에서 내가 할 수있는 도움을 제공하기 위해 답변을 업데이트했습니다. . 불행히도 약간 불가능한 문제입니다.
ShZ

3

이에 대한 빠른 해결책은 앱의 _ _ init _ _.py에 다음 코드를 배치하는 것입니다.

from django.contrib.auth.signals import user_logged_in
from django.dispatch import receiver


@receiver(user_logged_in)
def on_login(sender, user, request, **kwargs):
    print('User just logged in....')

1

신뢰할 수있는 유일한 방법 (사용자가 브라우저를 닫을 때도 감지)은 last_request사용자가 페이지를로드 할 때마다 일부 필드 를 업데이트 하는 것입니다.

사용자가 페이지를 연 경우 x 분마다 서버를 ping하는주기적인 AJAX 요청이있을 수도 있습니다.

그런 다음 최근 사용자 목록을 가져 와서 작업을 만들고 해당 목록에없는 사용자에 대한 작업을 지우는 단일 백그라운드 작업을 만듭니다.


사용자의 로그인 여부를 측정하는 가장 좋은 방법입니다. 기본적으로 로그인 한 사용자 명단을 유지하고 마지막 액세스가 무엇인지 확인하고 시간 제한을 결정해야합니다. 시간 제한을 10 분과 같이 설정 한 다음 페이지가 활성 상태 인 동안 각 웹 페이지가 5 분마다 Ajax 요청을 호출하도록하면 상태를 최신 상태로 유지해야합니다.
Jordan Reiter

1

(아무도 수행하지 않는) 버튼을 명시 적으로 클릭하는 것과 달리 로그 아웃을 추론하는 것은 "로그 아웃"에 해당하는 유휴 시간을 선택하는 것을 의미합니다. phpMyAdmin은 기본값 인 15 분을 사용하고 일부 은행 사이트에서는 5 분만 사용합니다.

이를 구현하는 가장 간단한 방법은 쿠키 수명을 변경하는 것입니다. 을 지정하여 전체 사이트에 대해이 작업을 수행 할 수 있습니다 settings.SESSION_COOKIE_AGE. 또는을 사용하여 사용자별로 (임의의 기준 집합에 따라) 변경할 수 있습니다 HttpResponse.setcookie(). 고유 한 버전을 만들고 render_to_response()각 응답의 수명을 설정 하여이 코드를 중앙 집중화 할 수 있습니다 .


0

대략적인 아이디어-이를 위해 미들웨어를 사용할 수 있습니다. 이 미들웨어는 관련 URL이 요청되면 요청을 처리하고 신호를 발생시킬 수 있습니다. 또한 주어진 행동이 실제로 성공했을 때 반응과 발사 신호를 처리 할 수 ​​있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.