Program Tip

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

programtip 2020. 10. 23. 08:20
반응형

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


내 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 모델에 속합니다.

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


다음과 같은 신호를 사용할 수 있습니다 (나는 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/ 주제 / 신호 /


한 가지 옵션은 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. 사용자가 로그인 할 때마다 로그 아웃 신호를 실행합니다. 또한 만료 된 세션을 플러시하기 위해 상당히 자주 실행되는 크론 작업을 만듭니다. 만료 된 세션이 삭제되면 세션의 사용자 (익명이 아닌 경우)에 더 이상 활성 세션이 없는지 확인합니다.이 경우 로그 아웃 신호를 발생시킵니다.

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


@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앱 디렉토리에 넣으면 다음을 추가하십시오 app.py.

def ready(self):
    import app_name.signals`

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

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

Then have a single background job that gets a list of recent users, create jobs for them, and clear the jobs for users not present in that list.


Inferring logout, as opposed to having them explicitly click a button (which nobody does), means picking an amount of idle time that equates to "logged out". phpMyAdmin uses a default of 15 minutes, some banking sites use as little as 5 minutes.

The simplest way of implementing this would be to change the cookie-lifetime. You can do this for your entire site by specifying settings.SESSION_COOKIE_AGE. Alternatively, you could change it on a per-user basis (based on some arbitrary set of criteria) by using HttpResponse.setcookie(). You can centralize this code by creating your own version of render_to_response() and having it set the lifetime on each response.


a quick solution for this would be, in the _ _ init _ _.py of your app place the following code:

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....')

Rough idea - you could use middleware for this. This middleware could process requests and fire signal when relevant URL is requested. It could also process responses and fire signal when given action actually succeded.

참고URL : https://stackoverflow.com/questions/1990502/django-signal-when-user-logs-in

반응형