Computer >> Máy Tính >  >> Lập trình >> Ruby

Cách Rails Sessions hoạt động

Điều gì sẽ xảy ra nếu ứng dụng Rails của bạn không thể biết ai đang truy cập nó? Nếu bạn không biết rằng cùng một người yêu cầu hai trang khác nhau? Nếu tất cả dữ liệu bạn đã lưu trữ biến mất ngay sau khi bạn trả lại phản hồi?

Điều đó có thể tốt cho một trang web chủ yếu là tĩnh. Nhưng hầu hết các ứng dụng cần có khả năng lưu trữ một số dữ liệu về người dùng. Có thể đó là id người dùng hoặc ngôn ngữ ưa thích hoặc họ luôn muốn xem phiên bản máy tính để bàn của trang web của bạn trên iPad của họ.

session là nơi hoàn hảo để đặt loại dữ liệu này. Các bit dữ liệu nhỏ mà bạn muốn lưu giữ cho nhiều hơn một yêu cầu.

Các phiên dễ sử dụng:

session[:current_user_id] = @user.id

Nhưng chúng có thể có một chút kỳ diệu. Phiên là gì? Làm cách nào để Rails biết để hiển thị đúng dữ liệu cho đúng người? Và làm cách nào để bạn quyết định nơi bạn lưu giữ dữ liệu phiên của mình?

Phiên là gì?

Phiên chỉ là nơi lưu trữ dữ liệu trong một yêu cầu mà bạn có thể đọc trong các yêu cầu sau.

Bạn có thể đặt một số dữ liệu trong một hành động của trình điều khiển:

app / controllers / session_controller.rb
def create
  # ...
  session[:current_user_id] = @user.id
  # ...
end

Và đọc nó trong một cái khác:

app / controllers / users_controller.rb
def index
  current_user = User.find_by_id(session[:current_user_id])
  # ...
end

Nó có thể không có vẻ như thật thú vị. Nhưng cần có sự phối hợp giữa trình duyệt của người dùng và ứng dụng Rails của bạn để giúp mọi thứ kết nối với nhau. Và tất cả đều bắt đầu với cookie.

Khi bạn yêu cầu một trang web, máy chủ có thể đặt cookie khi nó phản hồi lại:

~ jweiss$ curl -I https://www.google.com | grep Set-Cookie

Set-Cookie: NID=67=J2xeyegolV0SSneukSOANOCoeuDQs7G1FDAK2j-nVyaoejz-4K6aouUQtyp5B_rK3Z7G-EwTIzDm7XQ3_ZUVNnFmlGfIHMAnZQNd4kM89VLzCsM0fZnr_N8-idASAfBEdS; expires=Wed, 16-Sep-2015 05:44:42 GMT; path=/; domain=.google.com; HttpOnly

Trình duyệt của bạn sẽ lưu trữ các cookie đó. Và cho đến khi cookie hết hạn, mỗi khi bạn đưa ra yêu cầu, trình duyệt của bạn sẽ gửi cookie trở lại máy chủ:

...
> GET / HTTP/1.1
> User-Agent: curl/7.37.1
> Host: www.google.com
> Accept: */*
> Cookie: NID=67=J2xeyegolV0SSneukSOANOCoeuDQs7G1FDAK2j-nVyaoejz-4K6aouUQtyp5B_rK3Z7G-EwTIzDm7XQ3_ZUVNnFmlGfIHMAnZQNd4kM89VLzCsM0fZnr_N8-idASAfBEdS; expires=Wed, 16-Sep-2015 05:44:42 GMT; path=/; domain=.google.com; HttpOnly
...

Nhiều cookie trông giống như vô nghĩa. Và họ phải làm vậy. Bởi vì thông tin bên trong cookie không dành cho người dùng. Ứng dụng Rails của bạn chịu trách nhiệm tìm hiểu ý nghĩa của cookie. Ứng dụng của bạn đặt nó, vì vậy ứng dụng của bạn có thể đọc nó.

Điều này liên quan gì đến một phiên?

Vì vậy, bạn có một cookie. Bạn đưa dữ liệu vào trong một lần yêu cầu và bạn sẽ nhận được dữ liệu tương tự trong lần tiếp theo. Sự khác biệt giữa phiên đó và phiên là gì?

Theo mặc định, trong Rails, không có nhiều sự khác biệt. Rails thực hiện một số hoạt động với cookie để làm cho nó an toàn hơn. Nhưng bên cạnh đó, nó hoạt động theo cách bạn mong đợi. Ứng dụng Rails của bạn đưa một số dữ liệu vào cookie, dữ liệu tương tự sẽ xuất hiện từ cookie. Nếu chỉ có tất cả điều này thì không có lý do gì để phân biệt phiên với cookie.

Nhưng không phải lúc nào cookie cũng là câu trả lời phù hợp cho dữ liệu phiên:

  • Bạn chỉ có thể lưu trữ khoảng 4kb dữ liệu trong một cookie.

    Đây là thường đủ, nhưng đôi khi không.

  • Cookie được gửi cùng với mọi yêu cầu bạn đưa ra.

    Cookie lớn có nghĩa là yêu cầu và phản hồi lớn hơn, có nghĩa là trang web chậm hơn.

  • Nếu bạn vô tình để lộ secret_key_base của mình , người dùng của bạn có thể thay đổi dữ liệu bạn đã đặt bên trong cookie của mình.

    Khi điều này bao gồm những thứ như current_user_id , bất kỳ ai cũng có thể trở thành bất kỳ người dùng nào họ muốn!

  • Lưu trữ sai loại dữ liệu bên trong cookie có thể không an toàn.

Nếu bạn cẩn thận, đây không phải là vấn đề lớn.

Nhưng khi bạn không thể lưu trữ dữ liệu phiên của mình bên trong cookie vì một trong những lý do sau, Rails có một số nơi khác để lưu giữ phiên của bạn:

Cửa hàng phiên thay thế

Tất cả các cửa hàng trong phiên mà không cửa hàng phiên cookie hoạt động theo cùng một cách. Nhưng dễ nhất là nghĩ đến việc sử dụng một ví dụ thực tế.

Nếu bạn đang theo dõi các phiên của mình bằng ActiveRecord:

  1. Khi bạn gọi session[:current_user_id] = 1 trong ứng dụng của bạn và một phiên chưa tồn tại:

  2. Rails sẽ tạo một bản ghi mới trong session của bạn bảng có ID phiên ngẫu nhiên (giả sử, 09497d46978bf6f32265fefb5cc52264 ).

  3. Nó sẽ lưu trữ {current_user_id: 1} (Được mã hóa base64) trong dữ liệu data thuộc tính của bản ghi đó.

  4. Và nó sẽ trả về ID phiên đã tạo, 09497d46978bf6f32265fefb5cc52264 , vào trình duyệt bằng Set-Cookie .

Lần tới khi bạn yêu cầu một trang,

  1. Trình duyệt gửi cùng một cookie đó đến ứng dụng của bạn, sử dụng Cookie: tiêu đề.

    (như thế này:Cookie: _my_app_session=09497d46978bf6f32265fefb5cc52264;
    path=/; HttpOnly )

  2. Khi bạn gọi session[:current_user_id] :

  3. Ứng dụng của bạn lấy ID phiên ra khỏi cookie của bạn và tìm bản ghi của nó trong session bảng.

  4. Sau đó, nó trả về current_user_id ra khỏi data thuộc tính của bản ghi đó.

Cho dù bạn đang lưu trữ các phiên trong cơ sở dữ liệu, trong Memcached, trong Redis hay bất kỳ nơi nào khác, chúng hầu hết đều tuân theo cùng một quy trình này. Chỉ cookie của bạn chứa ID phiên và ứng dụng Rails của bạn tra cứu dữ liệu trong cửa hàng phiên của bạn bằng ID đó.

Khi nó hoạt động, lưu trữ các phiên của bạn trong cookie cho đến nay là cách dễ dàng nhất để thực hiện. Nó không cần thêm bất kỳ cơ sở hạ tầng hoặc thiết lập nào.

Nhưng nếu bạn cần vượt ra ngoài kho lưu trữ phiên cookie, bạn có hai lựa chọn:

Lưu trữ các phiên trong cơ sở dữ liệu hoặc lưu trữ chúng trong bộ nhớ cache của bạn.

Lưu trữ các phiên trong bộ nhớ cache

Bạn có thể đã sử dụng một cái gì đó như Memcache để lưu vào bộ nhớ cache các phần hoặc dữ liệu của mình. Nếu vậy, bộ nhớ cache là nơi dễ thứ hai để lưu trữ dữ liệu phiên, vì nó đã được thiết lập.

Bạn không phải lo lắng về việc lưu trữ phiên của mình phát triển ngoài tầm kiểm soát vì các phiên cũ hơn sẽ tự động bị loại bỏ khỏi bộ nhớ cache nếu nó quá lớn. Và nó nhanh chóng, vì bộ nhớ cache của bạn rất có thể sẽ được lưu trong bộ nhớ.

Nhưng nó không hoàn hảo:

  • Nếu bạn thực sự quan tâm đến việc duy trì các phiên cũ, có thể bạn không muốn chúng bị loại bỏ khỏi bộ nhớ cache.

  • Các phiên của bạn và dữ liệu đã lưu trong bộ nhớ cache của bạn sẽ tranh giành không gian. Nếu bạn không có đủ bộ nhớ, bạn có thể phải đối mặt với rất nhiều lần bỏ lỡ bộ nhớ cache và các phiên hết hạn sớm.

  • Nếu bạn cần đặt lại bộ nhớ cache của mình (giả sử bạn đã nâng cấp Rails và dữ liệu được lưu trong bộ nhớ cache cũ của bạn không còn chính xác nữa), không có cách nào để làm điều đó mà không hết hạn mọi người phiên.

Tuy nhiên, đây là cách chúng tôi lưu trữ dữ liệu phiên tại Avvo và nó hoạt động tốt cho chúng tôi cho đến nay.

Lưu trữ phiên trong cơ sở dữ liệu

Nếu bạn muốn giữ lại dữ liệu phiên của mình cho đến khi nó hết hạn hợp pháp, bạn có thể muốn giữ nó trong một số loại cơ sở dữ liệu. Cho dù đó là Redis, ActiveRecord hay thứ gì khác.

Nhưng lưu trữ phiên cơ sở dữ liệu cũng có nhược điểm:

  • Với một số kho lưu trữ cơ sở dữ liệu, các phiên của bạn sẽ không được dọn dẹp tự động.

    Vì vậy, bạn sẽ phải tự mình thực hiện và làm sạch các phiên đã hết hạn.

  • Bạn phải biết cơ sở dữ liệu của mình sẽ hoạt động như thế nào khi có đầy đủ dữ liệu phiên.

    Bạn có đang sử dụng Redis làm cửa hàng phiên của mình không? Nó sẽ cố gắng giữ tất cả dữ liệu phiên của bạn trong bộ nhớ? Máy chủ của bạn có đủ bộ nhớ cho việc đó không, hay nó sẽ bắt đầu hoán đổi quá mức khiến bạn không thể ssh sửa nó?

  • Bạn phải cẩn thận hơn về thời điểm tạo dữ liệu phiên, nếu không bạn sẽ lấp đầy cơ sở dữ liệu của mình bằng các phiên vô ích.

    Ví dụ:nếu bạn vô tình chạm vào phiên theo mọi yêu cầu, googlebot có thể tạo ra hàng trăm nghìn phiên vô ích. Và đó sẽ là khoảng thời gian tồi tệ.

Hầu hết những vấn đề này là khá hiếm. Nhưng bạn vẫn nên biết về chúng.

Vậy bạn nên lưu trữ các phiên của mình như thế nào?

Nếu bạn chắc chắn rằng mình sẽ không gặp phải bất kỳ giới hạn nào của cửa hàng cookie, hãy sử dụng nó. Nó không cần thiết lập nhiều và không phải đau đầu để duy trì.

Lưu trữ các phiên trong bộ nhớ cache so với cơ sở dữ liệu là một lời kêu gọi phán xét về mức độ tồi tệ của việc kết thúc phiên sớm. Tôi coi dữ liệu phiên là khá tạm thời, vì vậy bộ nhớ cache lưu trữ hoạt động tốt cho tôi. Vì vậy, tôi thường thử cookie trước, sau đó đến bộ nhớ cache, sau đó là cơ sở dữ liệu.

Nhưng còn bạn thì sao? Làm thế nào để bạn lưu trữ của bạn phiên họp? Để lại bình luận và cho tôi biết!

Và nếu bạn muốn tìm hiểu thêm về cách hoạt động của nội bộ Ruby và Rails, hãy xem bài viết này:Đá quý hoạt động như thế nào? Hoặc, nếu bạn quan tâm hơn đến cách web hoạt động, hãy xem Máy chủ web so với máy chủ ứng dụng.