~/journal/2025/01/implementing-google-login-in-rails-without-devise

在 Ruby on Rails 中实现 Google 登录,无需 Devise

如何在 Rails 8 中使用 OmniAuth 和内置的认证生成器实现 Google OAuth 登录,而不依赖 Devise。

发布
阅读时间
2 分钟
标签
Rails

本页由 AI 从原文翻译。

在本文中,我们将探讨如何在 Rails 8 中,基于 Rails 内置的认证系统,使用 OmniAuth 实现 Google 登录,而无需 Devise。

创建基本认证

生成认证

在 Rails 8 中,自带一个认证生成器,我们可以直接使用。它会创建 User 和 Session 模型,以及登录应用所需的控制器和视图。更多信息请参阅 官方指南

zsh
bin/rails generate authentication

移除密码

因为我只想启用 Google 登录,并移除其他登录方式。所以,数据库中的 users.password_digest 列就没有必要保留了,同时删除相关文件。

让我们从 [timestamp]_create_users.rb 中移除 t.string :password_digest, null: false,并更新 User 模型,删除 hassecurepassword 这一行,因为它不再需要了。

运行迁移

然后迁移数据库,以添加 User 和 Session 表。

zsh
bin/rails db:migrate

实现 Google 登录

添加 OmniAuth Gem

将所需的 gem 添加到你的 Gemfile 中,然后运行 bundle install 来安装这些 gem。

ruby
# OmniAuth and Google OAuth  
gem "omniauth", "~> 2.1"  
gem "omniauth-google-oauth2", "~> 1.2"  
gem "omniauth-rails_csrf_protection", "~> 1.0"

配置 OmniAuth

为 OmniAuth 创建一个初始化器:

zsh
touch config/initializers/omniauth.rb

然后添加以下配置。

ruby
Rails.application.config.middleware.use OmniAuth::Builder do  
  provider :google_oauth2, ENV["GOOGLE_CLIENT_ID"], ENV["GOOGLE_CLIENT_SECRET"]  
end

确保在部署配置中设置了 GOOGLECLIENTID 和 GOOGLECLIENTSECRET 环境变量。请阅读 Google OAuth 官方文档,了解如何获取 GOOGLE_CLIENT_ID 和 GOOGLE_CLIENT_SECRET 的值。

创建 SocialAccount 模型

虽然本文只需要实现 Google 登录,但以后我们可能还需要添加其他登录方式,比如 GitHub 登录,所以最好将社交账户信息保存到另一个模型中。这里我们称之为 SocialAccount。

zsh
rails generate model SocialAccount user:references provider:string uid:string auth_data:json

接下来,我们按如下方式更新生成的模型:

ruby
class SocialAccount < ApplicationRecord  
  belongs_to :user  

  validates :provider, presence: true  
  validates :uid, presence: true, uniqueness: { scope: :provider }  

  def self.from_omniauth(auth)  
    social_account = find_or_initialize_by(provider: auth.provider, uid: auth.uid)  

    unless social_account.persisted?  
      user = User.find_or_create_by!(email_address: auth.info.email) do |u|  
        u.name = auth.info.name  
        u.avatar_url = auth.info.image  
      end  

      social_account.user = user  
      social_account.save!  
    end  

    social_account  
  end  
end

我们添加了函数 self.from_omniauth,用于通过电子邮件创建或查找 User。

更新路由和 SessionsController

接下来,我们需要在 config/routes.rb 文件中添加 oauth 路由。

ruby
get "/auth/:provider/callback", to: "sessions#create"  
get "/auth/failure", to: "sessions#failure"

然后,更新 SessionsController

ruby
class SessionsController < ApplicationController  
  def create  
    auth = request.env["omniauth.auth"]  
    social_account = SocialAccount.from_omniauth(auth)  

    start_new_session_for social_account.user  
    redirect_to after_authentication_url  
  end  

  def failure  
    redirect_to root_path, alert: "Authentication failed, please try again."  
  end  
end

添加 Google 登录按钮

在 sessions/new.html.erb 中添加一个 Google 登录按钮:

erb
<%= button_to "Sign in with Google",  
    "/auth/google_oauth2",  
    method: :post,  
    class: "btn btn--primary btn--block",  
    data: { turbo: false } %>

现在,我们已经成功地为 Rails 应用添加了 Google 登录功能。

结论

通过这种设置,你可以在 Rails 应用中实现 Google 登录,而无需使用 Devise。借助 OmniAuth,你还可以扩展应用以支持其他提供商,如 Facebook 或 GitHub。

Epona
作者Epona

There's nothing wrong with having a little fun

x.com/simura_epona

相关文章

正在加载评论…