Django에서 비활성으로 인해 세션을 만료하는 방법은 무엇입니까?


93

Django 애플리케이션에는 다음과 같은 세션 관리 요구 사항이 있습니다.

  1. 사용자가 브라우저를 닫으면 세션이 만료됩니다.
  2. 세션은 비활성 기간이 지나면 만료됩니다.
  3. 비활성으로 인해 세션이 만료되는시기를 감지하고 사용자에게 적절한 메시지를 표시합니다.
  4. 비활성 기간이 끝나기 몇 분 전에 사용자에게 임박한 세션 만료를 경고합니다. 경고와 함께 사용자에게 세션을 연장 할 수있는 옵션을 제공합니다.
  5. 사용자가 서버에 요청을 전송하지 않는 앱 내에서 긴 비즈니스 활동을 수행하는 경우 세션이 시간 초과되지 않아야합니다.

문서, Django 코드 및 이와 관련된 블로그 게시물을 읽은 후 다음과 같은 구현 방법을 찾았습니다.

요구 사항 1
이 요구 사항은 SESSION_EXPIRE_AT_BROWSER_CLOSE를 True로 설정하여 쉽게 구현됩니다.

요구 사항 2
세션 만료 기간을 설정하기 위해 SESSION_COOKIE_AGE를 사용하기위한 몇 가지 권장 사항을 확인했습니다. 그러나이 방법에는 다음과 같은 문제점이 있습니다.

  • 세션은 사용자가 응용 프로그램을 적극적으로 사용하고 있더라도 항상 SESSION_COOKIE_AGE가 끝나면 만료됩니다. (사용자 지정 미들웨어를 사용하여 모든 요청에 ​​대해 세션 만료를 SESSION_COOKIE_AGE로 설정하거나 SESSION_SAVE_EVERY_REQUEST를 true로 설정하여 모든 요청에 ​​세션을 저장하여 방지 할 수 있습니다. 그러나 다음 문제는 SESSION_COOKIE_AGE 사용으로 인해 불가피합니다.)

  • 쿠키가 작동하는 방식으로 인해 SESSION_EXPIRE_AT_BROWSER_CLOSE 및 SESSION_COOKIE_AGE는 상호 배타적입니다. 즉, 쿠키는 브라우저를 닫을 때 또는 지정된 만료 시간에 만료됩니다. SESSION_COOKIE_AGE를 사용하고 쿠키가 만료되기 전에 사용자가 브라우저를 닫으면 쿠키가 유지되고 브라우저를 다시 열면 사용자 (또는 다른 사람)가 재 인증없이 시스템에 액세스 할 수 있습니다.

  • Django는 세션이 활성 상태인지 확인하기 위해 존재하는 쿠키에만 의존합니다. 세션과 함께 저장된 세션 만료 날짜를 확인하지 않습니다.

다음 방법을 사용하여이 요구 사항을 구현하고 위에서 언급 한 문제를 해결할 수 있습니다.

  • SESSION_COOKIE_AGE를 설정하지 마십시오.
  • 모든 요청에서 세션 만료 날짜를 '현재 시간 + 비활성 기간'으로 설정합니다.
  • SessionMiddleware에서 process_request를 재정의하고 세션 만료를 확인합니다. 세션이 만료 된 경우 폐기하십시오.

요구 사항 3
세션이 만료되었음을 감지하면 (위의 사용자 지정 SessionMiddleware에서) 세션 만료를 나타내는 요청에 속성을 설정합니다. 이 속성은 사용자에게 적절한 메시지를 표시하는 데 사용할 수 있습니다.

요구 사항 4
JavaScript를 사용하여 사용자 비활성을 감지하고 경고를 제공하며 세션을 확장하는 옵션도 제공합니다. 사용자가 확장을 원하면 세션을 확장하기 위해 연결 유지 펄스를 서버에 보냅니다.

요구 사항 5
JavaScript를 사용하여 사용자 활동을 감지하고 (긴 비즈니스 운영 중) 세션 만료를 방지하기 위해 활성 상태 유지 펄스를 서버에 보냅니다.


위의 구현 접근 방식은 매우 정교 해 보이며 더 간단한 방법이 있는지 궁금합니다 (특히 요구 사항 2의 경우).

모든 통찰력을 높이 평가할 것입니다.


3
+1 세부 솔루션 제공
Don

필요한 것을 할 수있는 미들웨어가 있습니다. githubpypi
gbutler

1
"쿠키가 작동하는 방식으로 인해 SESSION_EXPIRE_AT_BROWSER_CLOSE 및 SESSION_COOKIE_AGE는 상호 배타적입니다. 즉, 쿠키는 브라우저를 닫거나 지정된 만료 시간에 만료됩니다. SESSION_COOKIE_AGE를 사용하고 쿠키가 만료되기 전에 사용자가 브라우저를 닫으면 쿠키가 유지되고 다시 열립니다. 브라우저는 사용자 (또는 다른 사람)가 재 인증없이 시스템에 들어갈 수 있도록합니다. " 내가 틀렸다면 정정하십시오.하지만 최신 Django 버전에서는 더 이상 사실이 아닌 것 같습니다. (최소 1.5+)
Botond Béres 2014

1
"Django는 세션이 활성 상태인지 확인하기 위해 존재하는 쿠키에만 의존합니다. 세션과 함께 저장된 세션 만료 날짜를 확인하지 않습니다." 이것은 더 이상 사실아닙니다 .
knaperek

답변:


44

여기에 아이디어가 SESSION_EXPIRE_AT_BROWSER_CLOSE있습니다. 설정을 사용하여 브라우저를 닫으면 세션이 만료 됩니다. 그런 다음 모든 요청에 ​​대해 세션에 타임 스탬프를 설정합니다.

request.session['last_activity'] = datetime.now()

세션이 만료되었는지 감지하기 위해 미들웨어를 추가하십시오. 이와 같은 것이 전체 프로세스를 처리해야합니다.

from datetime import datetime
from django.http import HttpResponseRedirect

class SessionExpiredMiddleware:
    def process_request(request):
        last_activity = request.session['last_activity']
        now = datetime.now()

        if (now - last_activity).minutes > 10:
            # Do logout / expire session
            # and then...
            return HttpResponseRedirect("LOGIN_PAGE_URL")

        if not request.is_ajax():
            # don't set this for ajax requests or else your
            # expired session checks will keep the session from
            # expiring :)
            request.session['last_activity'] = now

그런 다음 세션 만료와 관련된 ajax 호출에 관련 데이터를 반환하기 위해 URL과 뷰를 만들어야합니다.

사용자가 세션을 "갱신"하기로 선택하면 requeset.session['last_activity']다시 말해서 현재 시간으로 설정 하기 만하면됩니다.

분명히이 코드는 시작일뿐입니다 ...하지만 올바른 경로로 안내해야합니다.


나는 여기서 회의적이지만 if not request.is_ajax()완전히 안전 하다고 생각하지 않습니다 . 세션 만료 전 스푸핑 / Ajax 전화를 보내 세션을 계속 진행할 수없는 사람이 있습니까?
notbad.jpeg 2013 년

2
@ notbad.jpeg : 일반적으로 "활동"은 쉽게 스푸핑 할 수 있습니다. 세션을 유지하고 요청을 계속 보내는 사람은 활성 상태입니다.
RemcoGerlich

이것은 훌륭한 대답입니다. 미들웨어는 Django 개발에서 매우 잘 활용되지 않는 도구입니다.
제이미 카운셀

30

저는 Django를 처음 사용했습니다.

로그인 한 사용자가 브라우저를 닫거나 일정 시간 동안 유휴 상태 (비 활동 시간 초과) 상태이면 세션이 만료되도록하고 싶었습니다. 알아 내기 위해 검색했을 때이 SOF 질문이 먼저 나왔습니다. 좋은 답변 덕분에 Django에서 요청 / 응답주기 동안 미들웨어가 어떻게 작동하는지 이해하기 위해 리소스를 찾았습니다. 매우 도움이되었습니다.

여기에있는 최상위 답변에 따라 사용자 정의 미들웨어를 코드에 적용하려고했습니다. 하지만 2011 년에 여기의 베스트 답변이 수정 되었기 때문에 조금은 의심 스러웠습니다. 최근 검색 결과에서 조금 더 시간을 들여서 간단한 방법을 생각해 냈습니다.

SESSION_EXPIRE_AT_BROWSER_CLOSE = True
SESSION_COOKIE_AGE = 10 # set just 10 seconds to test
SESSION_SAVE_EVERY_REQUEST = True

다른 브라우저는 확인하지 않고 크롬을 확인했습니다. 1. SESSION_COOKIE_AGE가 설정되어 있어도 브라우저를 닫으면 세션이 만료되었습니다. 2. 10 초 이상 유휴 상태 일 때만 A 세션이 만료되었습니다. SESSION_SAVE_EVERY_REQUEST 덕분에 새로운 요청이 발생할 때마다 세션을 저장하고 만료 시간을 업데이트합니다.

이 기본 동작을 변경하려면 SESSION_SAVE_EVERY_REQUEST 설정을 True로 설정하십시오. True로 설정하면 Django는 매 요청마다 세션을 데이터베이스에 저장합니다.

세션 쿠키는 세션이 생성되거나 수정 된 경우에만 전송됩니다. SESSION_SAVE_EVERY_REQUEST가 True이면 모든 요청에 ​​대해 세션 쿠키가 전송됩니다.

마찬가지로 세션 쿠키의 만료 부분은 세션 쿠키가 전송 될 때마다 업데이트됩니다.

장고 매뉴얼 1.10

나처럼 Django에서 새로운 사람인 일부 사람들은 내가 한 방식으로 해결책을 찾는 데 많은 시간을 소비하지 않도록 대답을 남깁니다.


26

django-session-security 가 바로 그 역할을합니다 ...

... 추가 요구 사항 : 서버가 응답하지 않거나 공격자가 인터넷 연결을 끊은 경우 : 어쨌든 만료되어야합니다.

Disclamer :이 앱을 유지합니다. 하지만 저는이 스레드를 아주 오랫동안 지켜 봤습니다. :)


1
멋진 앱-멋지게 디자인되고 잘 구축되었습니다. 멋지고 깨끗한 코드 ... 감사합니다.
nicorellius

사용자가 로그 아웃하지 않고 브라우저 나 탭을 닫아도 사용자가 로그 아웃하도록 강제합니까? 이 조건을 처리합니까?
Mehmet Kagan Kayaalp 2016

그것은 순수 http 세션 쿠키 만료에 의해 처리 될 것입니다.
jpic

10

두 번째 요구 사항을 충족하는 쉬운 방법 중 하나는 settings.py의 SESSION_COOKIE_AGE 값을 적절한 시간 (초)으로 설정하는 것입니다. 예를 들면 :

SESSION_COOKIE_AGE = 600      #10 minutes.

그러나 이렇게하면 사용자의 활동 여부에 관계없이 세션이 10 분 후에 만료됩니다. 이 문제를 해결하기 위해 사용자가 다음 문장으로 모든 종류의 요청을 수행 할 때마다 만료 시간이 자동으로 갱신 될 수 있습니다 (추가 10 분 동안 추가).

request.session.set_expiry(request.session.get_expiry_age())

2
SESSION_COOKIE_AGE = 600 새 페이지 요청이나 페이지 새로 고침이있을 때마다 세션 기간이 연장됩니다.
Aseem

1
설정 SESSION_COOKIE_AGE만으로 충분하며 모든 요청 (세션 쿠키 전송)이 자동으로 세션 쿠키 만료를 새로 고칠 것임을 확인합니다.
bruno desthuilliers


3

첫 번째 요청에서 세션 만료를 다음과 같이 설정할 수 있습니다.

self.request.session['access_key'] = access_key
self.request.session['access_token'] = access_token
self.request.session.set_expiry(set_age) #in seconds 

그리고 access_key와 토큰을 사용할 때

try:
    key = self.request.session['access_key']
except KeyError:
    age = self.request.session.get_expiry_age()
    if age > set_age:
        #redirect to login page
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.