Advertisement
  1. Code
  2. Ruby on Rails

Khám phá Devise, Phần 1

Scroll to top
Read Time: 12 min
This post is part of a series called Exploring Devise.
Exploring Devise, Part 2

Vietnamese (Tiếng Việt) translation by Dai Phong (you can also view the original English article)

Trong một số bài viết trước đây của tôi về upload hình ảnh trong Rails, tôi đã đề cập đến Devise nhưng không đi sâu vào nó. Trong hướng dẫn này, tôi sẽ dạy bạn về Devise.

Sẵn sàng chứ? Hãy bắt đầu thôi!

Giới thiệu Devise và các Mô-đun

Devise là một giải pháp xác thực cho Rails được tích hợp với Warden và được cung cấp bởi những người tuyệt vời tại Plataformatec. Devise cung cấp các mô-đun khác nhau:

  • Xác thực Cơ sở dữ liệu: Điều này mã hóa và lưu trữ một mật khẩu vào cơ sở dữ liệu để xác nhận tính xác thực của người dùng trong khi đăng nhập.
  • Xác thực với Omniauth: Điều này giúp cho OmniAuth có thể hỗ trợ cho Devise. Người dùng ứng dụng của bạn sẽ có thể đăng nhập bằng tài khoản như Facebook, Twitter và Google.
  • Xác nhận: Điều này cho phép việc gởi các email với các chỉ dẫn sẽ giúp xác nhận một tài khoản.
  • Khôi phục: Mô-đun này giúp những khi người dùng quên mật khẩu và cần phải khôi phục nó. Với điều này, thì người dùng sẽ có thể thiết lập lại mật khẩu.
  • Đăng ký: Điều này xử lý quá trình đăng ký của người dùng. Nó cũng cho phép người dùng chỉnh sửa và xoá các tài khoản của họ.
  • Khả năng nhớ: Mô-đun này làm cho ứng dụng của bạn có thể nhớ một người dùng đã đăng nhập bằng cách lưu trữ một cookie.
  • Theo dõi: Mô-đun này giúp theo dõi tài khoản đăng nhập, mốc thời gian, và địa chỉ IP.
  • Quá thời gian: Mô-đun này chịu trách nhiệm cho một phiên hết thời hạn mà đã không được kích hoạt trong một khoảng thời gian.
  • Kiểm tra hợp lệ: Với mô-đun này, email và mật khẩu sẽ được kiểm tra tính hợp lệ.
  • Khả năng khoá: Điều này cung cập một lớp phụ của bảo mật - khi được kích hoạt, một tài khoản có thể bị khoá sau một số lần cố gắng đăng nhập thất bại.

Tích hợp Devise

Với mục đích của hướng dẫn này, chúng ta sẽ tạo ra một ứng dụng Rails, mà chúng ta sẽ sử dụng để kiểm tra hoạt động của Devise. Hãy tiến hành thôi!

rails new devise-app -T

Cờ -T nói với Rails để tạo ra các ứng dụng mà không có bộ kiểm thử mặc định. Truy cập đến thư mục ứng dụng của bạn và thả các gem sau đây vào Gemfile của bạn.

1
#Gemfile
2
3
gem 'devise', '~> 4.1'
4
gem 'bootstrap-sass', '~> 3.3'

Bây giờ cài đặt Devise và các gem Bootstrap mà bạn vừa mới thêm vào.

bundle install

Đổi tên tập tin app/assets/stylesheets/application.css thành app/assets/stylesheets/application.scss và thêm các dòng sau đây vào đó:

1
#app/assets/stylesheets/application.scss
2
3
@import "bootstrap-sprockets";
4
@import "bootstrap";

Mở tập tin app/assets/javascripts/application.js và yêu cầu bootstrap-sprockets. Nó sẽ trông như thế này:

1
#app/assets/javascripts/application.js
2
3
//= require jquery
4
//= require bootstrap-sprockets
5
//= require jquery_ujs
6
//= require turbolinks
7
//= require_tree .

Tiếp theo, bạn cần phải chạy lệnh Rails để cài đặt các tập tin cấu hình cho Devise. Bạn làm điều đó bằng cách chạy lệnh này:

rails generate devise:install

Lệnh tạo ra các thứ sau đây trên terminal của bạn. Bạn nên đọc nó để hiểu những gì đã xảy ra.

1
create  config/initializers/devise.rb
2
     create  config/locales/devise.en.yml
3
===============================================================================
4
5
Some setup you must do manually if you haven't yet:
6
7
 1. Ensure you have defined default url options in your environments files. Here
8
    is an example of default_url_options appropriate for a development environment
9
    in config/environments/development.rb:
10
11
      config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
12
13
    In production, :host should be set to the actual host of your application.
14
15
 2. Ensure you have defined root_url to *something* in your config/routes.rb.
16
    For example:
17
18
      root to: "home#index"
19
20
 3. Ensure you have flash messages in app/views/layouts/application.html.erb.
21
    For example:
22
23
      <p class="notice"><%= notice %></p>
24
      <p class="alert"><%= alert %></p>
25
26
 4. If you are deploying on Heroku with Rails 3.2 only, you may want to set:
27
28
      config.assets.initialize_on_precompile = false
29
30
    On config/application.rb forcing your application to not access the DB
31
    or load models when precompiling your assets.
32
33
 5. You can copy Devise views (for customization) to your app by running:
34
35
      rails g devise:views
36
37
      ===============================================================================

Lệnh này cũng tạo ra hai tập tin, mà bạn có thể tìm thấy trong thư mục config. Nó cũng cung cấp cho chúng ta một số chỉ dẫn về những gì chúng ta nên làm.

Điều hướng đến layout ứng dụng của bạn, app/views/layouts/application.html.erb, và làm cho nó trông giống như những gì tôi có ở dưới đây:

1
#app/views/layouts/application.html.erb
2
3
<!DOCTYPE html>
4
<html>
5
<head>
6
  <title>DeviseApp</title>
7
  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>
8
  <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
9
  <%= csrf_meta_tags %>
10
</head>
11
<body>
12
  <div class="container-fluid">
13
    <p class="notice"><%= notice %></p>
14
    <p class="alert"><%= alert %></p>
15
  </div>
16
17
  <div class="container-fluid">
18
    <%= yield %>
19
  </div>
20
21
</body>
22
</html>

Bạn cần phải định nghĩa tùy chọn URL mặc định cho môi trường phát triển của bạn. Thêm code ở dưới vào config/environments/development.rb.

1
#config/environments/development.rb
2
3
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

Bây giờ bạn cần tạo ra một model User cho Devise. Bạn có thể làm điều này bằng cách sử dụng terminal của bạn.

rails generate devise User

Việc này sẽ tạo ra một tập tin user.rb trong thư mục app/models của bạn. Tập tin được tạo ra sẽ trông giống như thế này:

1
class User < ActiveRecord::Base
2
  # Include default devise modules. Others available are:
3
  # :confirmable, :lockable, :timeoutable and :omniauthable
4
  devise :database_authenticatable, :registerable,
5
         :recoverable, :rememberable, :trackable, :validatable
6
end

Bạn có thể thấy rằng nó có chứa các mô-đun mặc định mà tôi đã đề cập ở trên. Lệnh mà bạn chạy cũng sửa đổi tập tin config/routes.rb của bạn bằng cách thêm một route cho Devise. Bạn nên kiểm tra đó.

Tại thời điểm này, bạn cần phải di chuyển cơ sở dữ liệu của bạn. Bạn làm điều đó bằng cách chạy:

rake db:migrate

Xác thực bằng cách sử dụng Devise

Bây giờ bạn cần tạo ra một PagesController và bao quanh nó bằng Devise authentication - điều này sẽ ngăn chặn những người không được phép nhìn thấy trang.

rails generate controller Pages index

Mở tập tin routes của bạn và thiết lập thư mục gốc của ứng dụng của bạn.

1
#config/routes.rb
2
3
Rails.application.routes.draw do
4
  devise_for :users
5
  root to: "pages#index"
6
end

Mở PagesController của bạn ra và thêm sự xác thực cho trang index và new của bạn.

1
#app/controllers/pages_controller.rb
2
3
class PagesController < ApplicationController
4
  before_action :authenticate_user!, only: [:index, :new]
5
6
  def index
7
  end
8
9
  def new
10
  end
11
end

Đoạn mã chỉ ra rằng các trang indexnew chỉ có thể truy xuất bởi những người dùng đã đăng ký. Mở terminal của bạn và bắt đầu chạy rails server của bạn. Truy cập vào http://localhost:3000 trên trình duyệt và bạn sẽ tự động được chuyển hướng đến trang đăng nhập của Devise.

Đăng nhập mà không sử dụng Email

Theo mặc đinh các phương tiện đăng nhập vào Devise liên quan đến việc sử dụng email và mật khẩu. Nhưng nếu bạn muốn cho phép người dùng đăng nhập với username duy nhất của họ thì sao? Nếu đó là những gì bạn muốn, thì bạn hoàn toàn có thể. Chúng ta hãy xem cách làm thế nào.

Chạy lệnh:

rails generate migration AddUsernameToUSers username:string

Điều này sẽ thêm một cột mới cho username trong bảng users của bạn. Di chuyển cơ sở dữ liệu của bạn.

rake db:migrate

Bạn cần phải thêm một trường vào các view của bạn mà người dùng của bạn có thể nhập username của họ. Khi bạn truy cập đến thư mục app/views của bạn, bạn sẽ không tìm thấy bất kỳ tập nào kết xuất các view Devise của bạn. Điều này là bởi vì Devise tải các view từ bộ gem của nó. Để điều chỉnh nó, bạn có để tạo ra các bản sao của các view. Lệnh dưới đây thực hiện điều đó.

rails generate devise:views

Điều này sẽ tạo ra một số thư mục và tập tin trong thư mục app/views của bạn.

Bạn sẽ cần phải chỉnh sửa trang đăng nhập, đăng ký và cập nhật thông tin người dùng. Chỉ cần dán các đoạn mã dưới đây vào tập tin tương ứng của chúng.

Đăng ký

1
#app/views/devise/registrations/new.html.erb
2
3
<h2>Sign up</h2>
4
5
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
6
  <%= devise_error_messages! %>
7
8
  <div class="form-group">
9
    <%= f.label :email %><br />
10
    <%= f.email_field :email, autofocus: true, class: "form-control" %>
11
  </div>
12
13
  <div class="form-group">
14
    <%= f.label :username %>
15
    <%= f.text_field :username, class: "form-control" %>
16
  </div>
17
18
  <div class="form-group">
19
    <%= f.label :password %>
20
    <% if @minimum_password_length %>
21
    <em>(<%= @minimum_password_length %> characters minimum)</em>
22
    <% end %><br />
23
    <%= f.password_field :password, autocomplete: "off", class: "form-control" %>
24
  </div>
25
26
  <div class="form-group">
27
    <%= f.label :password_confirmation %><br />
28
    <%= f.password_field :password_confirmation, autocomplete: "off", class: "form-control" %>
29
  </div>
30
31
  <div class="actions">
32
    <%= f.submit "Sign up", class: "btn btn-primary" %>
33
  </div>
34
<% end %>
35
36
<%= render "devise/shared/links" %>

Chỉnh sửa

1
#app/views/devise/registrations/edit.html.erb
2
3
<h2>Edit <%= resource_name.to_s.humanize %></h2>
4
5
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
6
  <%= devise_error_messages! %>
7
8
  <div class="form-group">
9
    <%= f.label :email %><br />
10
    <%= f.email_field :email, autofocus: true, class: "form-control" %>
11
  </div>
12
13
  <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
14
    <div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
15
  <% end %>
16
17
  <div class="form-group">
18
    <%= f.label :username %>
19
    <%= f.text_field :username, class: "form-control" %>
20
  </div>
21
22
  <div class="form-group">
23
    <%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
24
    <%= f.password_field :password, autocomplete: "off", class: "form-control" %>
25
  </div>
26
27
  <div class="form-group">
28
    <%= f.label :password_confirmation %><br />
29
    <%= f.password_field :password_confirmation, autocomplete: "off", class: "form-control" %>
30
  </div>
31
32
  <div class="form-group">
33
    <%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
34
    <%= f.password_field :current_password, autocomplete: "off", class: "form-control" %>
35
  </div>
36
37
  <div class="actions">
38
    <%= f.submit "Update", class: "btn btn-primary" %>
39
  </div>
40
<% end %>
41
42
<h3>Cancel my account</h3>
43
44
<p>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %></p>
45
46
<%= link_to "Back", :back %>

Đăng nhập

1
#app/views/devise/sessions/new.html.erb
2
3
<h2>Log in</h2>
4
5
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
6
  <div class="form-group">
7
    <%= f.label :username %><br />
8
    <%= f.text_field :username, autofocus: true, class: "form-control" %>
9
  </div>
10
11
  <div class="form-group">
12
    <%= f.label :password %><br />
13
    <%= f.password_field :password, autocomplete: "off", class: "form-control" %>
14
  </div>
15
16
  <% if devise_mapping.rememberable? -%>
17
    <div class="form-group">
18
      <%= f.check_box :remember_me %>
19
      <%= f.label :remember_me %>
20
    </div>
21
  <% end -%>
22
23
  <div class="actions">
24
    <%= f.submit "Log in", class: "btn btn-primary" %>
25
  </div>
26
<% end %>
27
28
<%= render "devise/shared/links" %>

Sử dụng trình soạn thảo văn bản của bạn, điều hướng đến tập tin app/controllers/application_controller.rb. Bạn cần phải sửa đổi nó để cho phép việc sử dụng username. Sửa đổi nó sao cho trông giống như thế này:

1
#app/controllers/application_controller.rb
2
3
class ApplicationController < ActionController::Base
4
  # Prevent CSRF attacks by raising an exception.
5
  # For APIs, you may want to use :null_session instead.
6
  protect_from_forgery with: :exception
7
8
  before_action :configure_permitted_parameters, if: :devise_controller?
9
10
  protected
11
12
  def configure_permitted_parameters
13
    added_attrs = [:username, :email, :password, :password_confirmation, :remember_me]
14
    devise_parameter_sanitizer.permit :sign_up, keys: added_attrs
15
    devise_parameter_sanitizer.permit :account_update, keys: added_attrs
16
  end
17
end

Bây giờ người dùng có thể đăng nhập bằng username của mình. Tại thời điểm này, có một cái gì đó không đúng về ứng dụng của bạn. Khi người dùng đăng nhập vào, không có cách để đăng xuất. Điều này tạo ra hệ quả là một trải nghiệm người dùng không tốt. Tôi sẽ chỉ cho bạn cách khắc phục điều đó.

Từ terminal của bạn, tạo một thư mục mới gọi là shared trong thư mục app/views.

1
mkdir app/views/shared
2
touch app/views/shared/_navigation.html.erb

Tập tin mà bạn tạo ở trên là một phần nơi mà các mã cho thanh điều hướng của bạn sẽ được viết. Thả các mã sau đây vào đó.

1
#app/views/shared/_navigation.html.erb
2
3
<nav class="navbar navbar-inverse">
4
  <div class="container">
5
    <div class="navbar-header">
6
      <%= link_to 'Tutsplus Devise', root_path, class: 'navbar-brand' %>
7
    </div>
8
    <div id="navbar">
9
      <ul class="nav navbar-nav">
10
        <li><%= link_to 'Home', root_path %></li>
11
      </ul>
12
      <ul class="nav navbar-nav pull-right">
13
        <% if user_signed_in? %>
14
          <li class="dropdown">
15
            <a class="dropdown-toggle" data-toggle="dropdown" href="#">
16
              <%= current_user.name %>
17
              <span class="caret"></span>
18
            </a>
19
            <ul class="dropdown-menu" role="menu">
20
              <li><%= link_to 'Profile', edit_user_registration_path %></li>
21
              <li><%= link_to 'Log out', destroy_user_session_path, method: :delete %></li>
22
            </ul>
23
          </li>
24
        <% else %>
25
          <li><%= link_to 'Log In', new_user_session_path %></li>
26
          <li><%= link_to 'Sign Up', new_user_registration_path %></li>
27
        <% end %>
28
      </ul>
29
    </div>
30
  </div>
31
</nav>

Bây giờ bạn cần kết xuất thanh điều hướng trong layout ứng dụng của bạn. Mở tập tin app/views/layouts/application.html.erb và thả vào đó đoạn mã để kết xuất thanh điều hướng của bạn.

1
#app/views/layouts/application.html.erb
2
3
...
4
<div class="container-fluid">
5
  <%= render "shared/navigation" %>
6
7
  <p class="notice"><%= notice %></p>
8
  <p class="alert"><%= alert %></p>
9
</div>
10
...

Tổng kết

Trong phần này bạn đã học cách cài đặt Devise và thêm sự chứng thực vào trong các trang của bạn. Tôi cũng đã đề cập đến một bộ phận riêng. Tôi sẽ bao quát nó trong một bài hướng dẫn riêng.

Trong phần tiếp theo, chúng ta sẽ bao quát sâu hơn một số phần. Tôi hy vọng điều này xứng đáng với thời gian mà bạn đã bỏ ra!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.