使用者认证

Quality, Speed or Cheap. Pick two. - Unknown

使用者认证Authentication用以识别使用者身分,而授权Authorization则用来处理使用者有没有权限可以作哪些事情。

Authentication: 使用 Devise

devise是一套使用者认证(Authentication)套件,是Rails社群中最广为使用的一套。

  • 编辑 Gemfile 加上
  1. gem 'devise'
  • 输入bundle install安装此套件
  • 输入rails g devise:install产生devise设定档
  • 编辑 config/environments/development.rb 和 production.rb 加入寄信时默认的网站网址:
  1. config.action_mailer.default_url_options = { :host => 'localhost:3000' }
  • 确认 app/views/layouts/application.html.erb layout 中可以显示 flash 讯息,例如
  1. <p class="notice"><%= notice %></p>
  2. <p class="alert"><%= alert %></p>
  • 确认 routes.rb 中有设定网站首页位置,例如
  1. root :to => "welcome#index"
  • 输入rails g devise user产生 User model 及 Migration
  • 输入rails generate devise:views产生HTML样板,这会包括有注册、登入、忘记密码、Email等等页面,放在app/views/devise目录下。
  • 输入bin/rake db:migrate就会建立 users 资料表了

用法

  • 在需要登入的 controller 加上before_action :authenticate_user!
  • 可以在 Layout 中加上登入登出选单
  1. <% if current_user %>
  2. <%= link_to('登出', destroy_user_session_path, :method => :delete) %> |
  3. <%= link_to('修改密码', edit_registration_path(:user)) %>
  4. <% else %>
  5. <%= link_to('注册', new_registration_path(:user)) %> |
  6. <%= link_to('登入', new_session_path(:user)) %>
  7. <% end %>

加上自订字段到 Devise 的注册和编辑页面

Devise默认没有产生出first_namelast_name等等字段,例如我们来加一个nickname字段到User Model

  • rails g migration add_nickname_to_users,加上
  add_column :users, :nickname, :string
  • rake db:migrate 新增这个字段
  • 编辑application_controller.rb补上configure_permitted_parameters方法:
  class ApplicationController < ActionController::Base
    before_action :configure_permitted_parameters, if: :devise_controller?

    # ...

    protected

    def configure_permitted_parameters
      devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname])
      devise_parameter_sanitizer.permit(:account_update, keys: [:nickname])
    end
  end
  • 编辑views/devise/registrations/edit.html.erbviews/devise/registrations/new.html.erb,加上username字段
  <div><%= f.label :nickname %><br />
  <%= f.text_field :nickname %></div>

Authentication: 使用 Omniauth

除了使用上述的Devise自行处理使用者帐号密码之外,现在也非常流行直接使用外部的使用者认证系统,例如GoogleFacebookYahooGitHub等等,一来绝大部分的使用者都已经有了这些大网站的帐号,不需要再注册一次。二来你也不需要担心储存密码的安全性问题。这些第三方服务都使用一种叫做 OAuth 的开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,影片,联系人列表),而无需将用户名和密码提供给第三方应用。

这里我们使用的套件是Omniauth,他可以搭配各种不同的Provider厂商:

Devise 也可以和 Omniauth 整合在一起,请参考这份 Devise 的文件: https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview

Authorization

在让使用者登入之后,如果需要进一步设计使用者权限,可以这么做:

Simple Role-based Authorization

新增 migration,在 users 上加一个字段是 role

add_column :users, :role, :string

编辑 user.rb

def admin?
  self.role == "admin"
end

在 application_controller.rb 中加上:

protected

def authenticate_admin
  unless current_user.admin?
    flash[:alert] = "Not allow!"
    redirect_to root_path
  end
end

接着在需要保护的 Controller 加上

before_action :authenticate_user!  # 这个是 devise 提供的方法,先检查必须登入
before_action :authenticate_admin # 再检查是否有权限

这样就是最基本的用 role 来检查权限了。你可以在后台做使用者编辑的功能,可以选择有哪些角色。

除了自行实作之外,也有一些函式库可以帮助你设计,最知名的有两个 gem: