Chắc hẳn, nếu bạn làm việc với rails thì rất nhiều app của bạn có sử dụng một số framework xác thực người dùng như Devise, , Sorcery, Clearance, or Authlogic. Điểm chung của những framework này là chúng được xây dựng dựa trên Rails. Ngoài việc kế thừa những điểm tốt của rails thì chúng cũng kế thừa một số hạn chế như mô hình cồng kềnh, lạm dụng Active Record. Một lựa chọn đáng kể tới đó là sử dụng Rodauth. Khác với những framework khác được xây dựng dựa trên rails và Active Record, Rodauth được xây dựng dựa trên 2 gem là Roda và Sequel.
Logic xác thực mang tính bao đóng
Với Rodauth, tất cả các hành vi nhằm xác thực người dùng đều mang tính bao đóng trong một đối tượng Rodauth::Auth được tạo ra bên trong middleware của Roda và có quyền truy cập với các request.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <span class="token keyword">class</span> <span class="token class-name">RodauthMiddleware</span> <span class="token operator"><</span> <span class="token constant">Roda</span> <span class="token comment"># define your Rodauth configuration</span> plugin <span class="token symbol">:rodauth</span> <span class="token keyword">do</span> <span class="token comment"># load authentication features you need</span> enable <span class="token symbol">:login</span><span class="token punctuation">,</span> <span class="token symbol">:logout</span><span class="token punctuation">,</span> <span class="token symbol">:create_account</span><span class="token punctuation">,</span> <span class="token symbol">:verify_account</span><span class="token punctuation">,</span> <span class="token symbol">:reset_password</span> <span class="token comment"># change default settings</span> password_minimum_lenth <span class="token number">8</span> login_return_to_requested_location<span class="token operator">?</span> <span class="token boolean">true</span> reset_password_autologin<span class="token operator">?</span> <span class="token boolean">true</span> logout_redirect <span class="token string">"/"</span> <span class="token comment"># ...</span> <span class="token keyword">end</span> <span class="token comment"># handles requests before they reach the main app</span> route <span class="token keyword">do</span> <span class="token operator">|</span>r<span class="token operator">|</span> <span class="token comment"># handle Rodauth paths (/login, /create-account, /reset-password, ...)</span> r<span class="token punctuation">.</span>rodauth <span class="token comment"># require authentication for certain routes</span> <span class="token keyword">if</span> r<span class="token punctuation">.</span>path<span class="token punctuation">.</span>start_with<span class="token operator">?</span><span class="token punctuation">(</span><span class="token string">"/dashboard"</span><span class="token punctuation">)</span> rodauth<span class="token punctuation">.</span>require_authentication <span class="token keyword">end</span> <span class="token keyword">end</span> <span class="token keyword">end</span> |
Khi thêm app Roda trên vào middleware stack, block route sẽ được gọi với mỗi request trước khi nó đi tới app chính. R.rodauth sẽ xử lí các route, rodauth.require_authentication sẽ chuyển hướng tới trang đăng nhập nếu người dùng chưa đăng nhập. Tới cuối block, request sẽ được chuyển tới app chính. Các instance của Rodauth vẫn sẽ tồn tại trong controller và view, vì vậy bạn có thể yêu cầu xác thực ở trong controller nếu bạn muốn:
1 2 3 4 5 | <span class="token keyword">class</span> <span class="token class-name">PostsController</span> <span class="token operator"><</span> <span class="token constant">ApplicationController</span> before_action <span class="token operator">-</span><span class="token operator">></span> <span class="token punctuation">{</span> rodauth<span class="token punctuation">.</span>require_authentication <span class="token punctuation">}</span> <span class="token comment"># ...</span> <span class="token keyword">end</span> |
hoặc render ra link xác thực ở trong view:
1 2 3 4 5 6 7 | <span class="token operator"><</span><span class="token operator">%</span> <span class="token keyword">if</span> rodauth<span class="token punctuation">.</span>authenticated<span class="token operator">?</span> <span class="token string">%> <%= link_to "Sign out", rodauth.logout_path, method: :post %></span> <span class="token operator"><</span><span class="token operator">%</span> <span class="token keyword">else</span> <span class="token string">%> <%= link_to "Sign in", rodauth.login_path %></span> <span class="token operator"><</span><span class="token operator">%</span><span class="token operator">=</span> link_to <span class="token string">"Sign up"</span><span class="token punctuation">,</span> rodauth<span class="token punctuation">.</span>create_account_path <span class="token string">%> <% end %></span> |
Một số chức năng chính
Rdauth có tất cả các chức năng chính của một framework xác thực:
- Login/logout, nhớ mật khẩu.
- Tạo tài khoản với xác thực email.
- Đổi mật khẩu, reset mật khẩu.
- Đổi email với xác thực email.
- Khóa hoặc hủy tài khoản.
Bạn cũng sẽ thấy Rodauth có cả những tính năng bảo mật chuyện nghiệp như:
- Đặt thời hạn dùng cho mật khẩu, không cho dùng lại mật khẩu cũ.
- Kiểm tra độ phức tạp của mật khẩu, không cho dùng mật khẩu sơ sài.
- Đặt thời hạn sử dụng cho tài khoản và phiên đăng nhập.
Một số các tính năng khác:
- Xác thực qua HTTP
- Xác thực qua email
- Ghi nhật kí đăng nhập
- …
Uniform configuration DSL
Đối với Devise, có một số layer khác mà bạn có thể tùy chỉnh cách xác thực như: cài đặt global , cài đặt model , cài đặt controller và cài đặt routing . Một số cài đặt trên có thể tùy chỉnh động (dựa vào trạng thái của model hoặc controller), trong khi số còn lại chỉ có thể tùy chỉnh cứng. Và một số Hooks được kích hoạt ở model, trong khi số còn lại thì bạn phải ghi đè vào controller.
Đối với Rodauth, nó cung cấp một tùy chỉnh DSL đồng nhất cho phép thay đổi hầu như mọi hành vi xác thực được khai báo trong class Rodauth::Auth. Bạn có thể ghi đè một phương thức tùy chỉnh bằng cách tạo một giá trị tĩnh, hoặc truyền một block động.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token keyword">class</span> <span class="token class-name">RodauthApp</span> <span class="token operator"><</span> <span class="token constant">Roda</span> plugin <span class="token symbol">:rodauth</span> <span class="token keyword">do</span> <span class="token comment"># each feature adds its own set of configuration methods</span> enable <span class="token symbol">:login</span><span class="token punctuation">,</span> <span class="token symbol">:create_account</span><span class="token punctuation">,</span> <span class="token symbol">:verify_account_grace_period</span><span class="token punctuation">,</span> <span class="token symbol">:reset_password</span> <span class="token comment"># examples of static values:</span> login_redirect <span class="token string">"/dashboard"</span> <span class="token comment"># redirect to /dashboard after logging in</span> verify_account_grace_period <span class="token number">3.</span>days <span class="token comment"># allow unverified access for 3 days after registration</span> reset_password_autologin<span class="token operator">?</span> <span class="token boolean">true</span> <span class="token comment"># automatically log the user in after password reset</span> <span class="token comment"># examples of dynamic blocks:</span> password_minimum_length <span class="token punctuation">{</span> <span class="token constant">MyConfig</span><span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token symbol">:min_password_length</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># change minimum allowed password length</span> login_valid_email<span class="token operator">?</span> <span class="token punctuation">{</span> <span class="token operator">|</span>login<span class="token operator">|</span> <span class="token constant">TrueMail</span><span class="token punctuation">.</span>valid<span class="token operator">?</span><span class="token punctuation">(</span>login<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment"># override email validation logic</span> verify_account_redirect <span class="token punctuation">{</span> login_redirect <span class="token punctuation">}</span> <span class="token comment"># after account verification redirect to wherever login redirects to</span> <span class="token keyword">end</span> <span class="token keyword">end</span> |
Rodauth cung cấp một DSL cho việc phát triển các tính năng mới, giúp hợp lý hóa việc thêm các phương thức tùy chỉnh mới và tạo ra các hành vi xác thực linh hoạt nhất có thể
Một số tính năng khác
Các tính năng xác thực đã khai thác
Rodauth đã làm rất tốt trong việc làm các tính năng xác thực trở nên độc lập với nhau. Mỗi một tính năng đều được chứa trong một file duy nhất, code chỉ được load khi tính năng được kích hoạt. Điều này làm cho việc tìm hiểu các tính năng trở nên dễ dàng.
1 2 3 4 5 6 7 8 9 10 11 | enable <span class="token symbol">:create_account</span><span class="token punctuation">,</span> <span class="token comment"># create account and automatically login -- lib/features/rodauth/create_account.rb</span> <span class="token symbol">:verify_account</span><span class="token punctuation">,</span> <span class="token comment"># require email verification after account creation -- lib/features/rodauth/verify_account.rb</span> <span class="token symbol">:verify_account_grace_period</span><span class="token punctuation">,</span> <span class="token comment"># allow unverified login for a certain period of time -- lib/features/rodauth/verify_account_grace_period.rb</span> <span class="token symbol">:change_login</span><span class="token punctuation">,</span> <span class="token comment"># change email immediately -- lib/features/rodauth/change_login.rb</span> <span class="token symbol">:verify_login_change</span><span class="token punctuation">,</span> <span class="token comment"># require email verification before change is applied -- lib/features/rodauth/verify_login_change.rb</span> <span class="token symbol">:password_complexity</span><span class="token punctuation">,</span> <span class="token comment"># add password complexity requirements -- lib/features/rodauth/password_complexity.rb</span> <span class="token symbol">:disallow_common_passwords</span><span class="token punctuation">,</span> <span class="token comment"># don't allow using a weak common password -- lib/features/rodauth/disallow_common_passwords.rb</span> <span class="token symbol">:disallow_password_reuse</span><span class="token punctuation">,</span> <span class="token comment"># don't allow using a previously used password -- lib/features/rodauth/disallow_password_reuse.rb</span> |
Mỗi tính năng có một bảng cơ sở dữ liệu
Rodauth features are decoupled not only in code, but also in the database. Instead of adding all columns to a single table, in Rodauth each feature has a dedicated table. This makes it more transparent which database columns belong to which features.
Các tính năng của Rodauth đều độc lập không chỉ trong code mà còn trong cơ sở dữ liệu, thay vì thêm các cột trong một bảng thì mỗi tính năng của Rodauth lại có một bảng riêng. Điều này giúp phân biệt rõ các cột nào, bảng cơ sở dữ liệu nào thuộc về tính năng nào.
1 2 3 4 5 6 7 | create_table <span class="token symbol">:accounts</span> <span class="token keyword">do</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> <span class="token keyword">end</span> <span class="token comment"># used by base feature</span> create_table <span class="token symbol">:account_password_reset_keys</span> <span class="token keyword">do</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> <span class="token keyword">end</span> <span class="token comment"># used by reset_password feature</span> create_table <span class="token symbol">:account_verification_keys</span> <span class="token keyword">do</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> <span class="token keyword">end</span> <span class="token comment"># used by verify_account feature</span> create_table <span class="token symbol">:account_login_change_keys</span> <span class="token keyword">do</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> <span class="token keyword">end</span> <span class="token comment"># used by verify_login_change feature</span> create_table <span class="token symbol">:account_remember_keys</span> <span class="token keyword">do</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> <span class="token keyword">end</span> <span class="token comment"># used by remember feature</span> <span class="token comment"># ...</span> |
Kết luận
Rodauth là một trong những framework đem lại sự mới mẻ trong cách lập trình Ruby, cung cấp các thiết kế tiên tiến và dễ hiểu của các tính năng, được hỗ trợ bởi tính năng tùy chỉnh mạnh mẽ với DSL giúp tạo ra độ linh hoạt cao cho framework.