2010-06-11 26 views
72

Ứng dụng Django của chúng tôi có các yêu cầu quản lý phiên sau đây.Làm thế nào để hết hạn phiên do không hoạt động trong Django?

  1. Phiên hết hạn khi người dùng đóng trình duyệt.
  2. Phiên hết hạn sau một khoảng thời gian không hoạt động.
  3. Phát hiện khi phiên hết hạn do không hoạt động và hiển thị thông báo thích hợp cho người dùng.
  4. Cảnh báo người dùng phiên sắp xảy ra hết hạn sau vài phút trước khi kết thúc giai đoạn không hoạt động. Cùng với cảnh báo, cung cấp cho người dùng một tùy chọn để mở rộng phiên của họ.
  5. Nếu người dùng đang làm việc trên một hoạt động kinh doanh lâu dài trong ứng dụng không liên quan đến các yêu cầu được gửi đến máy chủ, phiên không được hết thời gian chờ.

Sau khi đọc tài liệu, mã Django và một số bài đăng trên blog liên quan đến điều này, tôi đã đưa ra cách tiếp cận triển khai sau.

Yêu cầu 1
Yêu cầu này có thể dễ dàng thực hiện bằng cách thiết lập SESSION_EXPIRE_AT_BROWSER_CLOSE True.

Yêu cầu 2
Tôi đã thấy một vài khuyến nghị sử dụng SESSION_COOKIE_AGE để thiết lập các phiên thời gian hết hạn. Nhưng phương pháp này có các vấn đề sau.

  • Phiên luôn hết hạn vào cuối SESSION_COOKIE_AGE ngay cả khi người dùng đang sử dụng ứng dụng. (Điều này có thể được ngăn chặn bằng cách đặt hết hạn phiên thành SESSION_COOKIE_AGE theo mọi yêu cầu bằng cách sử dụng phần mềm trung gian tùy chỉnh hoặc bằng cách lưu phiên trên mọi yêu cầu bằng cách đặt SESSION_SAVE_EVERY_REQUEST thành true. Nhưng vấn đề tiếp theo là không thể tránh khỏi do việc sử dụng SESSION_COOKIE_AGE.)

  • Do cách hoạt động của cookie, SESSION_EXPIRE_AT_BROWSER_CLOSE và SESSION_COOKIE_AGE loại trừ lẫn nhau tức là cookie hết hạn trên trình duyệt đóng hoặc vào thời điểm hết hạn được chỉ định. Nếu SESSION_COOKIE_AGE được sử dụng và người dùng đóng trình duyệt trước khi cookie hết hạn, cookie được giữ lại và mở lại trình duyệt sẽ cho phép người dùng (hoặc bất kỳ ai khác) vào hệ thống mà không được xác thực lại.

  • Django chỉ dựa vào cookie có mặt để xác định xem phiên có đang hoạt động hay không. Nó không kiểm tra ngày hết hạn phiên được lưu trữ với phiên.

Phương pháp sau có thể được sử dụng để thực hiện yêu cầu này và giải quyết các vấn đề nêu trên.

  • Không đặt SESSION_COOKIE_AGE.
  • Đặt ngày hết hạn của phiên là 'thời gian hiện tại + khoảng thời gian không hoạt động' trên mọi yêu cầu.
  • Ghi đè lên process_request trong SessionMiddleware và kiểm tra hết hạn phiên. Hủy phiên nếu nó đã hết hạn.

Yêu cầu 3
Khi chúng tôi phát hiện rằng phiên đã hết hạn (trong SessionMiddleware tùy chỉnh ở trên), thiết lập một thuộc tính theo yêu cầu để chỉ phiên hết hạn. Thuộc tính này có thể được sử dụng để hiển thị một thông báo thích hợp cho người dùng.

Yêu cầu 4
Sử dụng JavaScript để phát hiện người dùng không hoạt động, cung cấp cảnh báo và cũng là tùy chọn để kéo dài phiên. Nếu người dùng muốn mở rộng, hãy gửi một xung tiếp tục tới máy chủ để mở rộng phiên.

Yêu cầu 5
Sử dụng JavaScript để phát hiện hoạt động người dùng (trong hoạt động kinh doanh lâu) và gửi giữ xung còn sống đến máy chủ để ngăn chặn phiên từ đáo hạn.


Cách tiếp cận triển khai ở trên dường như rất phức tạp và tôi tự hỏi liệu có phương pháp đơn giản hơn (đặc biệt là Yêu cầu 2).

Mọi thông tin chi tiết sẽ được đánh giá cao.

+1

+1 để cung cấp giải pháp chi tiết – Don

+1

"Do cách hoạt động của cookie, SESSION_EXPIRE_AT_BROWSER_CLOSE và SESSION_COOKIE_AGE loại trừ lẫn nhau tức là cookie hết hạn trên trình duyệt hoặc vào thời điểm hết hạn đã chỉ định. Nếu SESSION_COOKIE_AGE được sử dụng và người dùng đóng trình duyệt trước khi cookie hết hạn, cookie được giữ lại và mở lại trình duyệt sẽ cho phép người dùng (hoặc bất kỳ ai khác) vào hệ thống mà không được xác thực lại. " Đúng tôi nếu tôi sai, nhưng điều này dường như không còn đúng trong phiên bản Django mới hơn? (1.5+ ít nhất) –

+0

Có một phần mềm trung gian có thể làm những gì bạn cần. [trên github] (https://github.com/subhranath/django-session-idle-timeout) và [trên pypi] (http://pypi.python.org/pypi/django-session-idle-timeout/1.3 .1) – gbutler

Trả lời

38

Đây là một ý tưởng ... Hết hạn phiên trên trình duyệt gần với cài đặt SESSION_EXPIRE_AT_BROWSER_CLOSE. Sau đó, đặt dấu thời gian trong phiên trên mọi yêu cầu như vậy.

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

và thêm phần mềm trung gian để phát hiện xem phiên đã hết hạn hay chưa. một cái gì đó như thế này sẽ xử lý toàn bộ quá trình ...

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 

Sau đó, bạn chỉ cần thực hiện một số url và chế độ xem để trả lại dữ liệu liên quan đến cuộc gọi ajax liên quan đến phiên hết hạn.

khi người dùng chọn để "làm mới" phiên giao dịch, có thể nói, tất cả các bạn phải làm là thiết lập requeset.session['last_activity'] đến thời điểm hiện tại lại

Rõ ràng mã này chỉ là một sự khởi đầu ... nhưng nó sẽ giúp bạn trên con đường đúng đắn

+0

Tôi chỉ đang hoài nghi ở đây, nhưng tôi không nghĩ rằng 'if not request.is_ajax()' là hoàn toàn an toàn. Không thể một người nào đó có được một cuộc họp của phiên trước khi hết hạn spoof/gửi một cuộc gọi ajax và giữ cho phiên đi? –

+2

@ notbad.jpeg: nói chung "hoạt động" có thể dễ dàng giả mạo.Người nào đó đang giữ phiên và tiếp tục gửi yêu cầu chỉ hoạt động. – RemcoGerlich

+0

Đây là một câu trả lời tuyệt vời. Middleware là một công cụ rất tận dụng trong phát triển Django. –

25

django-session-security không chỉ là ...

... với một yêu cầu bổ sung: nếu máy chủ không đáp ứng hoặc kẻ tấn công bị ngắt kết nối kết nối internet: nó sẽ hết hạn anyway.

Disclamer: Tôi duy trì ứng dụng này. Nhưng tôi đã theo dõi chủ đề này trong một thời gian rất, rất dài :)

+1

ứng dụng thú vị - được thiết kế đẹp mắt và được xây dựng tốt. đẹp, mã sạch ... cảm ơn. – nicorellius

+1

Thường xuyên cập nhật - cảm ơn jpic – datakid

+0

Nếu người dùng đóng trình duyệt hoặc tab (không đăng xuất) khi người đó rời đi, nó vẫn buộc người dùng đăng xuất? Nó có xử lý tình trạng này không? – waterkinq

3

Trong yêu cầu đầu tiên, bạn có thể đặt hết phiên như

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

và khi sử dụng access_key và mã thông báo,

try: 
    key = self.request.session['access_key'] 
except KeyError: 
    age = self.request.session.get_expiry_age() 
    if age > set_age: 
     #redirect to login page 
+0

Bỏ phiếu cho việc thiếu bình luận từ downvoter. – Ruraj

9

Một cách dễ dàng để đáp ứng yêu cầu thứ hai của bạn là đặt giá trị SESSION_COOKIE_AGE trong cài đặt.py đến một số lượng thích hợp của giây. Ví dụ:

SESSION_COOKIE_AGE = 600  #10 minutes. 

Tuy nhiên, chỉ thực hiện phiên này sẽ hết hạn sau 10 phút cho dù người dùng có trưng bày một số hoạt động hay không. Để đối phó với vấn đề này, thời gian hết hạn có thể được tự động gia hạn (đối với một phụ 10 phút) mỗi khi người dùng thực hiện bất kỳ loại yêu cầu với các câu sau đây:

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

Tôi chỉ khá mới để sử dụng Django.

Tôi muốn làm cho phiên hết hạn nếu người dùng đã đăng nhập đóng trình duyệt hoặc đang ở chế độ chờ (không hoạt động) trong một khoảng thời gian. Khi tôi googled nó để tìm ra, câu hỏi SOF này đã đưa ra đầu tiên. Nhờ có câu trả lời hay, tôi tra cứu tài nguyên để hiểu cách thức các phần mềm trung gian hoạt động trong chu kỳ yêu cầu/phản hồi ở Django. Nó rất hữu ích.

Tôi sắp áp dụng phần mềm trung gian tùy chỉnh vào mã của tôi sau câu trả lời hàng đầu ở đây. Nhưng tôi vẫn còn chút nghi ngờ vì câu trả lời hay nhất ở đây đã được chỉnh sửa vào năm 2011. Tôi đã dành nhiều thời gian hơn để tìm kiếm một chút từ kết quả tìm kiếm gần đây và đã đưa ra một cách đơn giản.

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

Tôi không kiểm tra các trình duyệt khác nhưng có chrome. 1. Phiên hết hạn khi tôi đóng trình duyệt ngay cả khi SESSION_COOKIE_AGE được đặt. 2. Chỉ khi tôi không hoạt động trong hơn 10 giây, Phiên đã hết hạn. Nhờ SESSION_SAVE_EVERY_REQUEST, bất cứ khi nào bạn xuất hiện yêu cầu mới, nó sẽ lưu phiên và cập nhật hết thời gian hết hạn

Để thay đổi hành vi mặc định này, hãy đặt cài đặt SESSION_SAVE_EVERY_REQUEST thành True. Khi được đặt thành True, Django sẽ lưu phiên vào cơ sở dữ liệu theo từng yêu cầu.

Lưu ý rằng cookie phiên chỉ được gửi khi phiên được tạo hoặc sửa đổi. Nếu SESSION_SAVE_EVERY_REQUEST là True, cookie phiên sẽ được gửi theo mọi yêu cầu.

Tương tự, phần hết hạn của cookie phiên được cập nhật mỗi khi cookie phiên được gửi.

django manual 1.10

tôi chỉ để lại câu trả lời để một số người là một loại mới trong Django như tôi không dành nhiều thời gian để tìm hiểu giải pháp như là một cách tôi đã làm.

+0

Bạn là người đàn ông !!! Cảm ơn bạn đã nghiên cứu. –

Các vấn đề liên quan