首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在devise和Rails5中使用omniauth-twitter gem

在devise和Rails5中使用omniauth-twitter gem
EN

Stack Overflow用户
提问于 2017-08-30 08:29:28
回答 1查看 411关注 0票数 0

我开始看Ryan Bates关于如何在devise中使用Omniauth的tutorial (rails-cast 235修订版)。我在处理user.rb文件时遇到问题。他在tutorial中显示的内容

代码语言:javascript
复制
devise :omniauthable, # ...

def self.from_omniauth(auth)
  where(auth.slice(:provider, :uid)).first_or_create do |user|
    user.provider = auth.provider
    user.uid = auth.uid
    user.username = auth.info.nickname
  end
end

def self.new_with_session(params, session)
  if session["devise.user_attributes"]
    new(session["devise.user_attributes"], without_protection: true) do |user|
      user.attributes = params
      user.valid?
    end
  else
    super
  end
end

def password_required?
  super && provider.blank?
end

def update_with_password(params, *options)
  if encrypted_password.blank?
    update_attributes(params, *options)
  else
    super
  end
end

对我不起作用,它显示了一个ActiveModel::ForbiddenAttributesError,并突出显示了这行代码where(auth.slice(:provider, :uid)).first_or_create do |user|。我想他的版本不能工作,因为我使用的是Rails5。不管怎样,我试着修改了user.rb文件。使用下面的代码。

代码语言:javascript
复制
 def self.from_omniauth(auth)
  where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
  	user.email = auth.info.email
    user.password = Devise.friendly_token[0,20]
    user.provider = auth.provider
    user.uid = auth.uid
    token = auth.credentials.token,
    secret = auth.credentials.secret
  end
end

def self.new_with_session(params, session)
    super.tap do |user|
      if data = session["devise.twitter_data"]
        # user.attributes = params
        user.update(
          email: params[:email],
          password: Devise.friendly_token[0,20],
          provider: data["provider"],
          uid: data["token"],
          token: data["credentials"]["token"],
          secret: data["credentials"]["secret"]
        )
      end
    end
  end

def password_required?
  super && provider.blank?
end

def update_with_password(params, *options)
  if encrypted_password.blank?
    update_attributes(params, *options)
  else
    super
  end
end
end

我能够让twitter身份验证页面显示加载大约一分钟,然后重定向回我的用户注册页面,而不需要登录,也不会显示任何错误消息。顺便说一下,有人知道如何使用devise登录facebook吗?

EN

回答 1

Stack Overflow用户

发布于 2017-08-30 12:05:53

该问题与您传递给self.from_omniauth(auth)的属性auth有关。您应该在服务器日志中设置一个binding.pryputs auth,以便查看此变量的外观。

可能当self.from_amniauth(auth)方法运行此auth.slice()时,它会以某种方式出错

此外,first_or_create方法可能正在创建用户,而您可能遗漏了某些内容,从而触发错误。所以试着在调试节目中使用user.errors.full_messages

希尔德的想法是,该方法的目的是找到或创建User。它是从控制器操作Users::OmniauthCallbacksController#facebook调用的

request表示这是从服务器到facebooktwitter的传出request

Facebook或Twitter将使用AJAX response回复此request,其中将包含您验证用户身份所需的信息。

代码语言:javascript
复制
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def facebook
    # You need to implement the method below in your model (e.g. app/models/user.rb)
    @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?, you probably saved the env variable
    else
      session["devise.facebook_data"] = request.env["omniauth.auth"]
      redirect_to new_user_registration_url
    end
  end

  def failure
    redirect_to root_path
  end, you probably saved the env variable
end

然后,使用下面的方法where(provider: auth.provider, uid: auth.uid).first_or_create,您可以创建user,也可以从您的数据库中find它。问题是你可能写错了这个方法,或者用错误的参数调用了它,或者你没有用twitter设置api来正确工作……

来自https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview

此操作有几个方面值得描述:

OmniAuth从Facebook检索到的所有信息都可以在request.env"omniauth.auth“上以哈希的形式获得。查看OmniAuth文档和每个omniauth-facebook gem的自述文件,了解返回了哪些信息。

找到有效用户后,可以使用以下两种方法之一进行登录: sign_in或sign_in_and_redirect。传递:event =>:身份验证是可选的。只有当您希望使用Warden回调时,才应该这样做。

也可以使用Devise的默认消息之一设置flash消息,但这取决于您。

如果用户没有持久化,我们将OmniAuth数据存储在会话中。请注意,我们使用“devise”存储此数据。作为键命名空间。这很有用,因为Devise删除了所有以“devise”开头的数据。无论何时用户登录,我们都会自动清理会话。最后,我们将用户重定向回我们的注册表单。

定义控制器后,我们需要在模型中实现from_omniauth方法(例如app/models/user.rb):

代码语言:javascript
复制
def self.from_omniauth(auth)
  where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
    user.email = auth.info.email
    user.password = Devise.friendly_token[0,20]
    user.name = auth.info.name   # assuming the user model has a name
    user.image = auth.info.image # assuming the user model has an image
    # If you are using confirmable and the provider(s) you use validate emails, 
    # uncomment the line below to skip the confirmation emails.
    # user.skip_confirmation!
  end
end

此方法尝试通过provider和uid字段查找现有用户。如果找不到用户,则会使用随机密码和一些额外信息创建一个新用户。请注意,在创建新用户时,first_or_create方法会自动设置provider和uid字段。first_or_create!方法的操作类似,不同之处在于,如果用户记录未通过验证,则它将引发异常。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45950152

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档