如何为Rails应用程序配置Devise和OmniAuth

来自菜鸟教程
跳转至:导航、​搜索

介绍

大多数 Ruby on Rails 应用程序都需要用户注册和身份验证机制。 从头开始开发这些需要大量的时间和精力——幸运的是,有 Devise。 使用 Devise gem,您可以在几分钟内建立一个成熟的用户身份验证系统。

但是,您可以让用户在不创建新帐户的情况下访问您的应用程序,从而让他们更快乐。 他们只需使用现有的 Facebook、Twitter、Amazon 或 DigitalOcean 帐户登录即可。 事实上,您可以支持任何流行的 OAuth 服务提供商的身份验证。 OAuth 支持由 OmniAuth gem 提供。 在本教程中,我们将创建一个使用 Devise 和 OmniAuth 的简单应用程序。

先决条件

在开始之前,请确保您的主机上安装了最新版本的 RVM、Ruby 和 Rails。 如果您不这样做,请按照此处的说明进行操作:如何在带有 RVM 的 Ubuntu 12.04 LTS 上安装 Ruby on Rails

本教程已经使用 Ruby 2.1.2 和 Rails 4.1.5 进行了测试。

第 1 步 - 创建一个新的 Rails 应用程序

建议您将所有 Rails 应用程序放在一个单独的目录中。

您现在应该创建一个。

mkdir rails_apps
cd rails_apps

在开始发出 Rails 命令之前,您必须初始化 RVM 环境。

如果您在学习本教程时休息一下,请记住每次重新启动终端会话时都要这样做。

. ~/.rvm/scripts/rvm
rvm use ruby --default

让我们将新应用程序称为 myapp。 创建应用程序后,使用 cd 进入应用程序的基本目录。

rails new myapp
cd myapp

注意:所有 Rails 命令都应该在应用程序的目录中运行,在本例中为 ~/rails_apps/myapp。

第 2 步 - 将所需的 Gem 添加到 Gemfile

我们需要 Devise 和 OmniAuth gems。 此外,您还需要为您希望支持的每个 OAuth 服务提供商提供一个单独的 gem。 对于本教程,我们将支持使用 DigitalOcean 登录,因此我们需要 omniauth-digitalocean gem。

将以下行添加到文件 ~/rails_apps/myapp/Gemfile 的末尾。 您可以使用 nano 作为文本编辑器。

gem 'therubyracer'
gem 'devise'
gem 'omniauth'
gem 'omniauth-digitalocean'

您将需要类似的 gem 来支持其他提供商。 例如,要支持 Facebook,您将需要 omniauth-facebook。 这里有一些这样的宝石供您参考:

  • 推特-omniauth-推特
  • 亚马逊-omniauth-amazon
  • 谷歌-omniauth-google
  • Github-omniauth-github

安装新添加的 gem。

bundle install

第 3 步 - 向应用程序添加基本功能

让我们快速添加几个页面到这个应用程序中进行测试。 最终,这些页面只有在登录后才能访问。

为此,我们可以使用 Rails 的脚手架功能。 使用 rails g scaffold 命令,我们只需指定模型的详细信息,Rails 就会生成功能齐全的页面来对该模型执行 CRUD(创建读取更新删除)操作。 换句话说,所有关联的控制器和视图都与模型文件一起生成。

rails g scaffold Product name:string price:integer description:text
rake db:migrate

接下来,我们必须定义这个应用程序的根。

编辑 ~/rails_apps/myapp/config/routes.rb,并添加行 root 'products#index' 以指定应用程序的根目录,就在现有 resources 行的下方。 您可以忽略所有被注释掉的行。 完成后,文件中的活动行将如下所示:

Rails.application.routes.draw do
  resources :products
  root 'products#index'
end

来吧,现在测试你的应用程序。 通过键入以下内容启动开发服务器:

rails s

从浏览器访问 http://localhost:3000/。 如果您正在远程开发,请将 localhost 替换为适合您的 Droplet 的 IP 地址或域。 3000 是开发服务器的默认端口号。

目前,不需要登录。 通过单击“新产品”添加几个产品。 一旦您对应用程序按预期工作感到满意,请返回终端并按 Ctrl+C 停止服务器。

第 4 步 - 设置设计

键入以下命令以添加 Devise 身份验证支持。

rails generate devise:install
rails generate devise User
rake db:migrate

这会添加登录和注册表单,以及所有相关的逻辑。

我们的应用程序现在有一个基本的身份验证系统,用户可以在其中注册自己,然后登录。 但是,所有页面仍然可以直接访问。 要更改此设置,请编辑 ~/rails_apps/myapp/app/controllers/application_controller.rb 并添加 authenticate_user! 作为在提供任何页面之前必须执行的操作。

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_action :authenticate_user!
end

如果您愿意,您可以使用 rails s 命令再次启动开发服务器,并通过访问 http://localhost:3000/ 查看这些新添加的页面(同样,使用您自己的域或 IP 地址) . 您应该会看到如下所示的页面:

您可以访问http://localhost:3000/users/sign_up注册为新用户。

第 5 步 - 更新用户模型以支持 OmniAuth

如果您再次启动服务器,请使用 CTRL-C 停止它。 向 Devise 生成的模型添加一个名为 uid 的新列。

rails g migration AddColumnsToUsers provider uid
rake db:migrate

第 6 步 - 从 OAuth 服务提供商处获取客户端 ID 和客户端密码

访问服务提供商的网站并在那里注册您的应用程序。 所有服务提供商都有不同的注册程序。 对于 DigitalOcean,请参阅此处的教程:如何以用户或开发者身份使用 DigitalOcean 的 OAuth 身份验证

在注册过程中,系统会要求您提供回调 URL。 每个提供者都有一个单独的回调 URL。 以下是一些流行的服务提供商的回调 URL:

  • 数字海洋:http://localhost:3000/users/auth/digitalocean/callback
  • 脸书:http://localhost:3000/users/auth/facebook/callback
  • 亚马逊:http://localhost:3000/users/auth/amazon/callback
  • 推特:http://localhost:3000/users/auth/twitter/callback
  • 谷歌:http://localhost:3000/users/auth/google/callback

请将 localhost 替换为可解析为您的 Droplet 的 IP 地址或域。 在注册过程结束时,您将获得您的客户端 ID 和客户端密码。 您将在下一步中使用这些值。

第 7 步 - 更新设计初始化程序

编辑 ~/rails_apps/myapp/config/initializers/devise.rb 以在文件底部添加客户端 ID 和机密,就在 end 行之前。 将 mailer_sender 更新为具有您自己的服务器名称和用户的名称也是一个好主意。 除了这两项之外,您无需进行任何其他更改。

编辑后,您的文件将如下所示(文件中还会有许多注释行):

Devise.setup do |config|
  #Replace example.com with your own domain name
  config.mailer_sender = 'mailer@example.com'

  require 'devise/orm/active_record'
  config.case_insensitive_keys = [ :email ]
  config.strip_whitespace_keys = [ :email ]
  config.skip_session_storage = [:http_auth]
  config.stretches = Rails.env.test? ? 1 : 10
  config.reconfirmable = true
  config.expire_all_remember_me_on_sign_out = true
  config.password_length = 8..128
  config.reset_password_within = 6.hours
  config.sign_out_via = :delete

  #Add your ID and secret here
  #ID first, secret second
  config.omniauth :digitalocean, "db381dc9990be7e3bc42503d0", "5b0824c2722b65d29965f1a1df"
end

第 8 步 - 更新用户模型

必须更改 Devise 生成的用户模型以指定我们要使用的服务提供者。 我们将三个项目添加到现有列表中(:omniauthable, :omniauth_providers => [:digitalocean],不要忘记额外的逗号!)。 我们还创建了一个名为 from_omniauth 的新方法来提取身份验证后可用的信息。

编辑后,您的 ~/rails_apps/myapp/app/models/user.rb 应如下所示:

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,
     :omniauthable, :omniauth_providers => [:digitalocean]

  def self.from_omniauth(auth)
      where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
        user.provider = auth.provider
        user.uid = auth.uid
        user.email = auth.info.email
        user.password = Devise.friendly_token[0,20]
      end
  end
end

保存文件。

第 9 步 - 添加一个控制器来处理回调 URL

首先,编辑 ~/rails_apps/myapp/config/routes.rb 并更新 devise_for 行以指定将处理回调的控制器的名称。 让我们简单地称它为 callbacks。 您的文件现在应该如下所示(减去注释部分):

Rails.application.routes.draw do
  devise_for :users, :controllers => { :omniauth_callbacks => "callbacks" }
  resources :products
  root 'products#index'
end

然后,创建一个新文件 ~/rails_apps/myapp/app/controllers/callbacks_controller.rb

向其中添加以下代码:

class CallbacksController < Devise::OmniauthCallbacksController
    def digitalocean
        @user = User.from_omniauth(request.env["omniauth.auth"])
        sign_in_and_redirect @user
    end
end

如果您使用了更多的 OAuth 提供者,则需要为它们中的每一个提供单独的方法。 方法的名称应与提供者的名称相匹配。 例如,要添加对 Facebook 的支持,您的方法将使用 def facebook 定义。

您的应用程序现已准备就绪。 再次启动您的服务器:

rails s

访问您的主页。 由于我们正在测试登录功能,您可能希望在没有存储数据的会话中执行此操作,例如 Chrome 隐身窗口。 您应该会看到 使用 Digitalocean 登录链接。 点击它。 您应该被重定向到 DigitalOcean 的登录页面。 成功登录后,您将被重定向回您自己的应用程序,并显示产品页面。

结论

您现在拥有适用于您的应用程序的现代用户身份验证系统,用户可以使用电子邮件地址、社交网络帐户或其他流行服务登录。

如果您决定在 Droplet 上将此应用程序投入生产,您可以参考此处的教程:如何使用 DigitalOcean One Click Image 启动您的 Ruby on Rails 应用程序。 如果您将应用添加到新的 Droplet,请不要忘记返回第 6 步,使用生产服务器的回调 URL 更新您的 DigitalOcean API 设置。