Rails 8 đã ra mắt được vài tháng, và mình thì cũng bận bịu đợt này nên giờ mới có 1 bài lên. Và bài lần này mình sẽ nói về 1 tính năng được PR khá mạnh: Authentication được tích hợp ở Rails 8, được viết trực tiếp bởi DHH luôn.
Chúng ta sẽ cùng nhìn đoạn dưới đây ở CHANGELOG để có tổng quan.
Add authentication generator to give a basic start to an authentication system using database-tracked sessions and password reset.
Generate with...
bin/rails generate authentication
Generated files:
app/models/current.rb
app/models/user.rb
app/models/session.rb
app/controllers/sessions_controller.rb
app/controllers/passwords_controller.rb
app/mailers/passwords_mailer.rb
app/views/sessions/new.html.erb
app/views/passwords/new.html.erb
app/views/passwords/edit.html.erb
app/views/passwords_mailer/reset.html.erb
app/views/passwords_mailer/reset.text.erb
db/migrate/xxxxxxx_create_users.rb
db/migrate/xxxxxxx_create_sessions.rb
test/mailers/previews/passwords_mailer_preview.rb
Bắt đầu
Bước đầu thì tất nhiên là khởi tạo 1 project Rails 8 mới rồi =)) Lần này thì mình tạo project rails sẽ không dùng console mà dùng luôn plugin sẵn có của RubyMine(do đang được ưu đãi free 6 tháng với cert Gold từ 2023)
Click vào File > New > Project để mở hộp thoại dưới đây ở RubyMine:
Tại hộp thoại, chọn mục Application, nhập tên project, đường dẫn, chọn version Ruby, version Rails và loại database. Với JavaScript mình chọn importmap vì muốn thử. Các bạn cũng vẫn có thể chọn 1 số option khác như Webpack hay là ESbuild đều được.
Ngoài ra, các lựa chọn Mountable Engine hay là Rails API cũng tuỳ theo lựa chọn của bạn.
Project sẽ tự tạo cho bạn với cấu trúc thư mục y như dưới đây
(Nhân tiện lưu ý hãy đưa .idea
vào .gitignore
nhé)
Nhìn chung với RubyMine đến từ JetBrains, thao tác project Ruby sẽ thành kéo thả support khá thú vị(cơ mà nếu quen chạy lệnh terminal rồi thì có cũng được mà không có cũng không sao)
(Nhân tiện nếu không lười thì mình sẽ viết review về RubyMine cho các bạn sau. Nhưng nói qua thì tiện lợi và nóng máy như bao sản phẩm nhà JetBrain khác)
Authentication
Theo như hướng dẫn ở trên thì mình chạy
bin/rails generate authentication
Hoặc ở RubyMine, mình sẽ bật cửa sổ lệnh lên và gõ tìm kiếm rồi click
Các file được generate đúng hệt như ở phía trên
Phân tích
Models & migrations
Lần này có 3 model được sinh ra gồm User
, Current
và Session
được sinh ra. Có 2 migration là user
và session
.
- Bảng
users
sẽ có trườngemail_address
là unique và 1 trườngpassword_digest
chứa password được mã hoá vớihas_secure_password
. - Bảng
sessions
có 1 trườngtoken
, được tạo ra bằnghas_secure_token
ở modelSession
. Ngoài ra còn cóip_address
vàuser_agent
để ghi lại thông tin network và thông tin thiết bị của người dùng. - Model
Current
quản lý trạng thái theo yêu cầu và cung cấp quyền truy cập vào thông tin của người dùng hiện tại thông qua phương thứcuser
được ủy quyền. - Gem
bcrypt
sẽ được sử dụng, nên nếu chưa tồn tại ở Gemfile thì sẽ được thêm vào, hoặc nếu bị comment ở Gemfile thì sẽ được bỏ comment.
Authentication concern
Toàn bộ logic lần này đều được đưa vào Authentication concern.
require_authentication
: Đây là callbackbefore_action
cố gắng khôi phục phiên làm việc hiện tại bằngresume_session
. Nếu không tìm thấy phiên làm việc, nó sẽ chuyển hướng người dùng đến trang đăng nhập bằngrequest_authentication
.resume_session
: Truy xuất một phiên làm việc bằng cách sử dụng token đã ký từ cookie thông qua phương thứcfind_session_by_cookie
. Thiết lập nó làm phiên làm việc hiện tại và lưu token trong một cookie HTTP-only vĩnh viễn bằng phương thứcset_current_session
.authenticated?
: Một phương thức trợ giúp kiểm tra xem người dùng hiện tại có phiên làm việc đang hoạt động hay không.allow_unauthenticated_access
: Phương thức lớp này cho phép các hành động cụ thể bỏ qua callbackrequire_authentication
.after_authentication_url
: Trả về URL để chuyển hướng sau khi xác thực.start_new_session_for(user)
: Tạo một phiên làm việc mới cho người dùng đã cho với chi tiết về thiết bị và địa chỉ IP của người dùng, sau đó thiết lập phiên làm việc hiện tại.terminate_session
: Hủy phiên làm việc hiện tại và xóa token phiên làm việc khỏi cookie.
Controller
Để sử dụng authentication lần này, ở ApplicationController
, ta cần thêm
include Authentication
Sau đó ở mỗi controller trong source code Rails, ta cần đưa lên trên đầu file tương ứng gồm require_authentication
, allow_unauthenticated_access
hay resume_session
. Nếu so với devise
thì chỉ cần cái nào cần authen thì thêm, còn default là không cần thêm gì cả
Chưa có sign up hay cơ chế gì để đăng ký user mới
Mình có chạy thử 1 loạt và kết quả là login khá là mượt mà. Nhưng...
- Chưa có cơ chế đăng ký user mới
- Ở routes, các route sẽ được định nghĩa như sau
resource :session resources :passwords, param: :token
Mình đã tạo 1 link sign up, nhưng cũng phải mất công custom lại route vì path đăng ký của mình là /sign_up
, còn path đăng nhập lại là /session/new
Kết
Rails 8 đã và đang tích hợp nhiều tính năng, tạo sự thuận lợi cho dev, và tính năng authentication dự kiến là có thể cho gem devise
nghỉ hưu... Cơ mà sau vài version nữa. Chúng ta hãy cùng đợi các version trong tương lai hoặc tạo pull request để fix nào.