Rails – Xác thực user – Phần 2


Được đăng vào ngày 07/12/2016 | 0 bình luận
Đánh giá bài viết

Trong phần này chúng ta sẽ tiếp tục xây dựng chức năng đăng nhập user.

Tạo controller

Đầu tiên chúng ta tạo 2 controller mới là sessionsadmin.

C:\Projects\Rails\depot>rails generate controller sessions new create destroy
...
C:\Projects\Rails\depot>rails generate controller admin index
...

Controller sessions sẽ có 3 phương thức là new, createdestroy. Trong đó:

  • new sẽ xử lý URL /login với phương thức GET, kết quả trả về trang hiển thị form đăng nhập
  • create sẽ xử lý URL /login với phương thức POST, trong đó kiểm tra thông tin username và password do người dùng gửi lên có chính xác không, sau đó lưu lại trong biến session rồi trả về trang /admin/index nếu đúng, không thì quay về lại trang /login (GET).
  • destroy sẽ xử lý URL /logout với phương thức DELETE, mục đích là để hủy biến session, tức là chức năng đăng xuất, sau đó trả về trang chủ là '/'.

Controller admin có một phương thức là index, xử lý URL /admin/index (GET), phương thức này sẽ hiển thị một số câu thông báo đơn giản chứ chưa làm gì nhiều ở đây.

Xử lý quá trình đăng nhập

Chúng ta sửa lại file sessions_controller.rb trong thư mục app/controllers như sau:

class SessionsController < ApplicationController
    def new 
    end

    def create 
        if user = User.authenticate(params[:name], params[:password])
            session[:user_id] = user.id
            redirect_to admin_url
        else
            redirect_to login_url, :alert => "Invalid username/password"
        end
    end

    def destroy
        session[:user_id] = nil
        redirect_to '/', :notice => "Logged out"
    end
end

Phương thức new để hiển thị form, chứ không xử lý gì cả nên chúng ta để không.

Phương thức create sẽ kiểm tra xem người dùng có đăng nhập đúng không bằng cách gọi phương thức authenticate trong lớp User mà chúng ta đã làm trong bài trước. Nếu đúng thì chúng ta tạo một phần tử trong biến session với key là :user_id và value là user.id, sau đó trả về trang 'admin/index' có trong biến admin_url.  Nếu user đăng nhập sai thì chúng ta trả về lại trang /login, kèm theo câu thông báo trong biến :alert.

Phương thức destroy sẽ xóa phần tử :user_id trong biến session, sau đó trả về trang '/', với câu thông báo trong biến :notice.

Tạo form đăng nhập

Như đã nói, form này được phương thức new trong lớp sessions_controller hiển thị từ file new.html.erb trong thư mục app/views/sessions, chúng ta sửa lại file này như sau:

<div class="depot_form">
    <% if flash[:alert] %>
        <p id="notice"><%= flash[:alert] %></p>
    <% end %>
 
    <% if notice %>
        <p id="notice"><%= notice %></p>
    <% end %>
    <%= form_tag '/login' do %>
        <fieldset>
            <legend>Log In</legend>
 
            <div>
                <label for="name">Name:</label>
                <%= text_field_tag :name, params[:name] %>
            </div>
 
            <div>
                <label for="password">Password:</label>
                <%= password_field_tag :password, params[:password] %>
            </div>
 
            <div>
                <%= submit_tag "Login" %>
            </div>
        </fieldset>
    <% end %>
</div>

Chúng ta hiển thị form và câu thông báo từ biến :alert nếu có (từ người dùng đã đăng nhập sai).

Khác với các phần trước là chúng ta tạo form từ model, tức là model có các trường gì thì chúng ta có thể tạo nhanh form cho model đó với phương thức helper là form_for. Còn ở đây chúng ta đang tạo form riêng, không có model nào cả, do đó chúng ta dùng phương thức helper là form_tag,

Phương thức form_tag có phương thức gửi mặc định là POST, URL mặc định là <tên_controller>/<tên_phương_thức>, tức là form này được tạo trong file new.html.erb (từ phương thức new trong controller sessions) thì mặc định URL gửi đi là /sessions/new. Nhưng ở đây chúng ta dùng URL riêng là /login luôn.

Bên trong chúng ta khai báo các trường bằng các phương thức helper khác như text_field_tag dùng để tạo textbox, password_field_tag dùng để tạo ô nhập password, submit_tag tạo nút Submit. Khi sử dụng các phương thức này thì chúng ta phải tự khai báo các idname.

Ngoài ra còn có rất nhiều các phương thức tạo nhanh form khác, bạn có thể xem tại đây.

Tạo trang admin/index

Ở đây trang /admin/index sẽ chưa làm gì nhiều, chúng ta sẽ tùy chỉnh sau:

<h1>Welcome</h1>

Time: <%= Time.now %> <br>
There are <%= pluralize(@total_orders, "order") %>.

<%= button_to 'Logout', '/logout', :method => :delete %>

Chúng ta cho hiển thị giờ hiện tại (trên máy tính) và tổng số lượng đơn hàng đã được tạo ra. Ở cuối trang là nút bấm dẫn đến URL '/logout' với phương thức gửi là DELETE.

Tổng số lượng đơn hàng được lấy từ biến @total_orders, do đó chúng ta khai báo biến này trong controller như sau:

class AdminController < ApplicationController
    def index
        @total_orders = Order.count
    end
end

Routing

Việc cần làm cuối cùng là phải tự tay điều hướng các URL mới vào các controller đã được tạo ở trên, bởi vì chúng ta tạo controller bằng tay chứ không được tạo tự động thông qua model như trước. Chúng ta sửa lại file config/routes.rb như sau:

Rails.application.routes.draw do
    get 'admin/index'

    get 'sessions/new'

    get 'sessions/create'

    get 'sessions/destroy'

    resources :users
    resources :orders
    resources :line_items
    resources :carts
    get 'store/index'

    resources :products do 
        get 'who_bought', :on => :member
    end
 
    root :to => 'store#index' 
 
    get 'admin' => 'admin#index'
 
    controller :sessions do
        get 'login' => :new
        post 'login' => :create
        delete 'logout' => :destroy
    end
end

Đối với trang /admin/index thì chúng ta dùng phương thức get rồi điều hướng vào phương thức index trong controller admin.

Đối với các controller có nhiều phương thức xử lý thì chúng ta có thể định nghĩa chúng gộp chung trong khối lệnh controller...do...end. Trong đó chúng ta cũng sử dụng các phương thức bình thường như get, post, delete, phương thức gửi đến có thể để theo dạng symbol chứ không cần phải khai báo rõ ra thành chuỗi (như 'sessions#new' hay 'sessions#create'…) nữa.

Bây giờ chúng ta có thể trỏ vào trang /login và đăng nhập được rồi.

Đăng nhập thành công:

Đăng xuất:







Trả lời


Lưu ý: bọc code trong cặp thẻ [code language="x"][/code] để highlight code.


Ví dụ:


[code language="cpp"]


    std::cout << "Hello world";


[/code]



Các ngôn ngữ được hỗ trợ gồm: actionscript3, bash, clojure, coldfusion, cpp, csharp, css, delphi, diff, erlang, fsharp, go, groovy, html, java, javafx, javascript, latex, matlab, objc, perl, php, powershell, python, r, ruby, scala, sql, text, vb, xml.

Thư điện tử của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *