【发布时间】:2016-08-10 09:02:47
【问题描述】:
我坚持将devise 与omniauth-facebook 集成
我的演示应用正在使用:
- 导轨 5
- 设计
- 权威人士
- OmniAuth (omniauth-facebook)
我在 Wiki 页面上遵循以下指南:https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview 但在创建用户时遇到问题。
它将登录用户并将应用添加到用户的 Facebook(在应用设置中),但它确实将帐户注册到 User 模型。
# Gemfile
source 'https://rubygems.org'
gem 'rails', '~> 5.0.0'
gem 'devise'
gem 'pundit'
gem 'omniauth-facebook'
# Gemfile.lock for the 3 authorization and authentication gems
GEM
remote: https://rubygems.org/
remote: https://rails-assets.org/
specs:
devise (4.2.0)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0, < 5.1)
responders
warden (~> 1.2.3)
pundit (1.1.0)
omniauth (1.3.1)
hashie (>= 1.2, < 4)
rack (>= 1.0, < 3)
omniauth-facebook (4.0.0)
omniauth-oauth2 (~> 1.2)
omniauth-oauth2 (1.4.0)
oauth2 (~> 1.0)
omniauth (~> 1.2)
用户模型的架构。
我添加了一个迁移provider:string 和uid:string
# == Schema Information
#
# Table name: users
#
# id :integer not null, primary key
# email :string default(""), not null
# encrypted_password :string default(""), not null
# reset_password_token :string
# reset_password_sent_at :datetime
# remember_created_at :datetime
# sign_in_count :integer default(0), not null
# current_sign_in_at :datetime
# last_sign_in_at :datetime
# current_sign_in_ip :inet
# last_sign_in_ip :inet
# created_at :datetime not null
# updated_at :datetime not null
# name :string default(""), not null
# provider :string
# uid :string
ApplicationController 包含 pundit 和 devise 代码:
class ApplicationController < ActionController::Base
include Pundit
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
private
def user_not_authorized
flash[:error] = "You are not authorized to perform this action."
redirect_to(request.referrer || root_path)
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
devise_parameter_sanitizer.permit(:account_update, keys: [:name])
end
end
我已将config/initializers/devise.rb 配置为在omniauth 配置中包含:facebook。
# File: config/initializers/devise.rb
# Use this hook to configure devise mailer, warden hooks and so forth.
# Many of these configuration options can be set straight in your model.
Devise.setup do |config|
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 : 11
config.reconfirmable = true
config.password_length = 6..128
config.email_regexp = /\A[^@\s]+@[^@\s]+\z/
config.sign_out_via = :delete
# ==> OmniAuth
# Add a new OmniAuth provider. Check the wiki for more information on setting
# up on your models and hooks.
# config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
config.omniauth :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_APP_SECRET'], callback_url: ENV['FACEBOOK_CALLBACK_URL'], scope: 'email', info_fields: 'email,name'
end
我已将omniauthable 添加到User 模型中。
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:omniauthable, omniauth_providers: [:facebook]
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.name = auth.info.name
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
end
end
def self.new_with_session(params, session)
super.tap do |user|
if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
user.email = data["email"] if user.email.blank?
end
end
end
end
我创建了一个OmniauthCallbacksController 来处理登录请求。
# File: app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
@user = User.from_omniauth(request.env["omniauth.auth"])
if @user.persisted?
sign_in_and_redirect @user, event: :authentication #this will throw if @user is not activated
set_flash_message(:notice, :success, kind: "Facebook") if is_navigational_format?
else
session["devise.facebook_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
def failure
redirect_to root_path
end
end
在Routes 我添加了以下内容:
# File: config/routes.rb
Rails.application.routes.draw do
devise_for :users, controllers: { omniauth_callbacks: "users/omniauth_callbacks" }
root 'pages#index'
end
将“使用 Facebook 登录”链接添加到 devise sessions#new 视图。
# File: app/views/devise/sessions/new.html.erb
<div class="login">
<%= link_to "Sign in with Facebook", user_facebook_omniauth_authorize_path %>
# This is the link it creates: <a href="/users/auth/facebook">Sign in with Facebook</a>
</div>
用户流程:
- 点击“使用 Facebook 登录”
- 用户被转发到 Facebook 的 Oauth 网址,提示“以用户身份继续”提示用户点击“确定”
- 用户返回应用,但用户未在数据库中注册
- url是一长串参数
code和state(检查*NB
*NB 从 Facebook 返回网址:
http://localhost:3000/?code=REALLYLONGHASHOFCHARACTERS&state=ANOTHERSETOFREALLYLONGHASHOFCHARACTERS
development.log 显示:
Started GET "/users/auth/facebook" for ::1 at 2016-08-10 18:43:26 +1000
I, [2016-08-10T18:43:26.084371 #2292] INFO -- omniauth: (facebook) Request phase initiated.
Started GET "/users/auth/facebook" for ::1 at 2016-08-10 18:43:26 +1000
I, [2016-08-10T18:43:26.521627 #2292] INFO -- omniauth: (facebook) Request phase initiated.
Started GET "/?code=REALLYLONGHASHOFCHARACTERS&state=ANOTHERSETOFREALLYLONGHASHOFCHARACTERS" for ::1 at 2016-08-10 18:44:19 +1000
Processing by ListingsController#index as HTML
Parameters: {"code"=>"REALLYLONGHASHOFCHARACTERS", "state"=>"ANOTHERSETOFREALLYLONGHASHOFCHARACTERS"}
我认为它不会触发Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController,因为我在facebook 操作上添加了raise "Error",但它不会引发任何错误。而且我在运行Rails routes时看不到omniauth_callbacks: "users/omniauth_callbacks"
查看路线显示:
# Routes
|| Prefix Verb URI Pattern Controller#Action
|| new_user_session GET /users/sign_in(.:format) devise/sessions#new
|| user_session POST /users/sign_in(.:format) devise/sessions#create
|| destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy
|| user_facebook_omniauth_authorize GET|POST /users/auth/facebook(.:format) users/omniauth_callbacks#passthru
|| user_facebook_omniauth_callback GET|POST /users/auth/facebook/callback(.:format) users/omniauth_callbacks#facebook
|| user_password POST /users/password(.:format) devise/passwords#create
|| new_user_password GET /users/password/new(.:format) devise/passwords#new
|| edit_user_password GET /users/password/edit(.:format) devise/passwords#edit
|| PATCH /users/password(.:format) devise/passwords#update
|| PUT /users/password(.:format) devise/passwords#update
|| cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel
|| user_registration POST /users(.:format) devise/registrations#create
|| new_user_registration GET /users/sign_up(.:format) devise/registrations#new
|| edit_user_registration GET /users/edit(.:format) devise/registrations#edit
|| PATCH /users(.:format) devise/registrations#update
|| PUT /users(.:format) devise/registrations#update
|| DELETE /users(.:format) devise/registrations#destroy
|| root GET / pages#index
我不知道从这里做什么。非常感谢任何帮助和见解。
【问题讨论】:
标签: ruby-on-rails devise omniauth ruby-on-rails-5 omniauth-facebook