- vừa được xem lúc

Devise Timeoutable

0 0 21

Người đăng: Vu Dong

Theo Viblo Asia

Với lập trình viên Ruby on Rails, việc sử dụng gem devise trong việc xác thực hẳn là không còn xa lạ với mọi người. Một gem vô cùng mạnh mẽ, linh hoạt với nhiều chiến lược xác thực khác nhau được hỗ trợ. Bài này của mình sẽ không đi sâu về gem này mà chỉ đơn giản là một chút nho nhỏ tìm hiểu về 1 trong các chiến lược đó của devise - timeoutable.

I. Giới thiệu về timeoutable

1. Giới thiệu

Đầu tiên, hãy xem qua phần mô tả của model này

Timeoutable takes care of verifying whether a user session has already expired or not. When a session expires after the configured time, the user will be asked for credentials again, it means, they will be redirected to the sign in page

Có thể tạm hiểu đơn giản, nếu sử dụng timeoutable, devise sẽ kiểm tra việc user session đã hết hạn hay chưa. Nếu như session hết hạn sau một khoảng thời gian (được set trong cài đặt) thì người dùng sẽ cần đăng nhập lại (điều hướng về trang đăng nhập).

2. Sử dụng

Ở đây mình code một đoạn nho nhỏ demo cho chiến lược này. Đầu tiên cần thêm devise vào dự án

gem 'devise'

Thực hiện cài đặt gem với bundler

bundle install

Tiếp theo là cài đặt phần khởi tạo devise

rails generate devise:install

Lệnh này sẽ tạo ra 2 file

  • config/initializers/devise.rb: khởi tạo và setup cho devise
  • config/locales/devise.en.yml: hỗ trợ cho i18n của devise

Tạm thời chúng ta chưa quan tâm nhiều tới các file này. Sau khi đã có các file generator, chúng ta cần một model để sử dụng cho xác thực với devise

rails generate devise User

Thực hiện migrate db

rails db:migrate

Để đảm bảo xác thực thì trong app/controllers/application_controller.rb chúng ta sẽ kiểm tra xác thực trước mỗi action

class ApplicationController < ActionController::Base before_action :authenticate_user!
end

Tạm thời như vậy, khởi động server nào

rails s -p 3000

Mặc định, model được tạo ra sẽ như sau

class User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable
end

Trước tiên cứ khởi tạo một user đã

User.create(email: '_@.com', password: '12345678', password_confirmation: '12345678')

Khi thực hiện đăng nhập, session của user sẽ là kiểu session

Do model hiện tại không có timeoutable, session này sẽ không bị kiểm tra thời gian hết hạn. Vậy có vấn đề gì với một session không hết hạn? Với ý này, chúng ta có thể tham khảo qua phần security của ruby on rails:

Sessions that never expire extend the time-frame for attacks such as cross-site request forgery (CSRF), session hijacking, and session fixation.

Có thể hiểu đơn giản, một session khi nó không bị hết hạn thì các tấn công vào trang web có rất nhiều thời gian để có thể thực hiện. Việc giới hạn thời gian tồn tại của session sẽ hạn chế khoảng thời gian mà hacker có thể khai thác với 1 session hắn có được (bằng nhiều cách khác nhau).

3. Timeoutable

Với devise để có thể hạn chế thời gian tồn tại của một session, chúng ta sẽ bổ sung thêm chiến lược timeoutable:

class User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, :timeoutable
end

Tiếp theo, ta có thể khai báo khoảng thời gian tồn tại của session.

Nếu dùng cho riêng 1 model, ta thêm trực tiếp trong model:

class User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, :timeoutable, timeout_in: 1.minutes
end

Nếu muốn dùng chung cho các model, có thể khai báo trong file config/initializers/devise.rb

config.timeout_in = 1.minutes

Khi này, các session sẽ có thời hạn là 1 phút tính từ request cuối cùng mà session này thực hiện.

Video demo:

II. Magic behind the scene

Vậy devise đã làm như thế nào để có thể kiểm tra nhưng điều này?

Trước tiên, ta sẽ xem xét cách mà devise thực hiện hook vào quá trình xác thực tại đây.

Warden::Manager.after_set_user do |record, warden, options| scope = options[:scope] env = warden.request.env if record && record.respond_to?(:timedout?) && warden.authenticated?(scope) && options[:store] != false && !env['devise.skip_timeoutable'] last_request_at = warden.session(scope)['last_request_at'] if last_request_at.is_a? Integer last_request_at = Time.at(last_request_at).utc elsif last_request_at.is_a? String last_request_at = Time.parse(last_request_at) end proxy = Devise::Hooks::Proxy.new(warden) if !env['devise.skip_timeout'] && record.timedout?(last_request_at) && !proxy.remember_me_is_active?(record) Devise.sign_out_all_scopes ? proxy.sign_out : proxy.sign_out(scope) throw :warden, scope: scope, message: :timeout end unless env['devise.skip_trackable'] warden.session(scope)['last_request_at'] = Time.now.utc.to_i end end
end

Đầu tiên, devise sẽ hook vào trong quá trình xác thực của warden (gem thực hiện xác thực), lấy ra giá trị last_request_at của session hiện tại. Nếu như không có option skip timeout cũng như chọn remember me, việc kiểm tra timeout record.timedout?(last_request_at) trả về đúng thì sẽ thực hiện đăng xuất.

Vậy cùng xem qua trong hàm timedout? sẽ kiểm tra những gì

def timedout?(last_access) !timeout_in.nil? && last_access && last_access <= timeout_in.ago
end

Quá trình kiểm tra sẽ có các điều kiện

  • timeout_in đã được khai báo
  • lass_access không null
  • lass_access xảy ra trước timeout_in tính từ thời điểm hiện tại

Như vậy, timeoutable sẽ tính timeout của một session từ request cuối cùng mà session này được sử dụng.

III. Final

Bài này chỉ đơn giản là note lại của bản thân trong quá trình tìm hiểu và học về devise.

IV. References

Bình luận

Bài viết tương tự

- vừa được xem lúc

Tôi cá là bạn không biết những điều này - Ruby on rails ( Phần 2)

Các bạn có thể theo dõi phần 1 ở đây :. https://viblo.asia/p/toi-ca-la-ban-khong-biet-nhung-dieu-nay-ruby-on-rails-phan-1-WAyK8DDeKxX. 5.

0 0 222

- vừa được xem lúc

Rails Memoization

Memoization is a process that can be used to speed up rails methods. It caches the results of methods that do time-consuming work, work that only needs to be done once. Here is an example. Example.

0 0 48

- vừa được xem lúc

Tại sao Rails lại dùng cả Webpack lẫn Sprocket?

Khi Rails 6 được ra mắt, có thể bạn đã từng tự hỏi. WTF, sao Webpack đã được add vào rồi, mà Sprocket vẫn tồn tại thế kia . Chẳng phải Webpack và Sprocket được dùng để giải quyết chung một công việc hay sao. Hoặc cả đây:.

0 0 59

- vừa được xem lúc

Bạn nên sử dụng Elasticsearch trong ứng dụng Ruby On Rails như thế nào?

Elasticsearch là một công cụ phân tích và mã nguồn mở mạnh mẽ và linh hoạt, phân tán, theo thời gian thực. Đó là tiêu chuẩn vàng trong công nghệ tìm kiếm.

0 0 80

- vừa được xem lúc

Form object pattern trong rails

1.Mở đầu.

0 0 111

- vừa được xem lúc

Sử dụng Twilio để gửi SMS trong ứng dụng Ruby on Rails

Ngoài cách xác nhận tài khoản hay gửi thông báo bằng email thì hôm nay mình sẽ hướng dẫn các bạn 1 cách nữa là thông qua SMS/Voice. Công cụ sử dụng sẽ là gem Twilio. Installation. Để cài đặt bằng Bundler, hãy lấy phiên bản mới nhất:.

0 0 67