- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试在 Rails 4 中制作一个应用程序。过去 3 年(除了 10 天)我一直在尝试让设计工作。
我正在尝试遵循本教程:http://sourcey.com/rails-4-omniauth-using-devise-with-twitter-facebook-and-linkedin/
请不要推荐其他教程/gem 文档。我已经尝试了至少 30 个其他教程,并且 gem 文档充满了我不理解的错误和组件。
我当前的问题是,当我完成本教程中的注册步骤时,表单会要求我提供电子邮件地址。
用户 Controller 有一个完成注册方法:
def finish_signup
# authorize! :update, @user
if request.patch? && params[:user] #&& params[:user][:email]
if @user.update(user_params)
@user.skip_reconfirmation!
# sign_in(@user, :bypass => true)
# redirect_to root_path, notice: 'Your profile was successfully updated.'
# redirect_to [@user, @user.profile || @user.build_profile]
sign_in_and_redirect(@user, :bypass => true)
else
@show_errors = true
end
end
end
当我尝试此操作时,出现此错误:
undefined method `match' for {:host=>"localhost", :port=>3000}:Hash
该行的错误点:
<div class="intpol3"><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></div>
我的开发环境设置为包含我的电子邮件发件人的所有配置详细信息。
当我在生产模式下尝试相同的步骤时,出现此错误:
ActionView::Template::Error (No route matches {:action=>"show", :controller=>"profiles", :id=>nil} missing required keys: [:id]):
它正在寻找配置文件 ID,因为我的用户模型中有一个 after_create 操作:
after_create :gen_profile
def gen_profile
Profile.create(user: self) # Associations must be defined correctly for this syntax, avoids using ID's directly.
# Profile.save
end
本教程的另一个问题是身份表中的字段未填充。
我很想找到已成功实现本教程或可以了解如何实现此功能的人。
我的代码是:
gem 文件
gem 'devise', '3.4.1'
gem 'devise_zxcvbn'
gem 'omniauth'
gem 'omniauth-oauth2', '1.3.1'
gem 'omniauth-google-oauth2'
gem 'omniauth-facebook'
gem 'omniauth-twitter'
gem 'omniauth-linkedin-oauth2'
gem 'google-api-client', require: 'google/api_client'
路线
devise_for :users, #class_name: 'FormUser',
:controllers => {
:registrations => "users/registrations",
# :omniauth_callbacks => "users/authentications"
:omniauth_callbacks => 'users/omniauth_callbacks'
}
# get '/auth/:provider/callback' => 'users/authentications#create'
# get '/authentications/sign_out', :to => 'users/authentications#destroy'
# PER SOURCEY TUTORIAL ----------
match '/users/:id/finish_signup' => 'users#finish_signup', via: [:get, :patch], :as => :finish_signup
resources :users do
resources :profiles, only: [:new, :create]
end
用户.rb
类用户
TEMP_EMAIL_PREFIX = 'change@me'
TEMP_EMAIL_REGEX = /\Achange@me/
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable,
:confirmable, :lockable,
# :zxcvbnable,
:omniauthable, :omniauth_providers => [:facebook, :linkedin, :twitter, :google_oauth2 ]
# --------------- associations
has_many :authentications, :dependent => :delete_all
has_one :profile
has_many :identities
# --------------- scopes
# --------------- validations
# validates_presence_of :first_name, :last_name
validates_uniqueness_of :email
# per sourcey tutorial - how do i confirm email registrations are unique?
# this is generating an error about the options in the without function -- cant figure out the solution
validates_format_of :email, :without => TEMP_EMAIL_REGEX, on: :update
# --------------- class methods
# sourcey tutorial
def self.find_for_oauth(auth, signed_in_resource = nil)
# Get the identity and user if they exist
identity = Identity.find_for_oauth(auth)
# If a signed_in_resource is provided it always overrides the existing user
# to prevent the identity being locked with accidentally created accounts.
# Note that this may leave zombie accounts (with no associated identity) which
# can be cleaned up at a later date.
user = signed_in_resource ? signed_in_resource : identity.user
# p '11111'
# Create the user if needed
if user.nil?
# p 22222
# Get the existing user by email if the provider gives us a verified email.
# If no verified email was provided we assign a temporary email and ask the
# user to verify it on the next step via UsersController.finish_signup
email_is_verified = auth.info.email && (auth.info.verified || auth.info.verified_email)
email = auth.info.email if email_is_verified # take out this if stmt for chin yi's solution
user = User.where(:email => email).first if email
# Create the user if it's a new registration
if user.nil?
# p 33333
user = User.new(
# at least one problem with this is that each provider uses different terms to desribe first name/last name/email. See notes on linkedin above
first_name: auth.info.first_name,
last_name: auth.info.last_name,
email: email ? email : "#{TEMP_EMAIL_PREFIX}-#{auth.uid}-#{auth.provider}.com",
#username: auth.info.nickname || auth.uid,
password: Devise.friendly_token[0,20])
# fallback for name fields - add nickname to user table
# debugger
# if email_is_verified
user.skip_confirmation!
# end
# user.skip_confirmation!
user.save!
end
end
# Associate the identity with the user if needed
if identity.user != user
identity.user = user
identity.save!
end
user
end
def email_verified?
self.email && TEMP_EMAIL_REGEX !~ self.email
end
用户 Controller
class UsersController < ApplicationController
before_action :set_user, only: [:index, :show, :edit, :update, :finish_signup, :destroy]
# i added finish_signup to the set_user action (not shown in tutorial)
def index
# if params[:approved] == "false"
# @users = User.find_all_by_approved(false)
# else
@users = User.all
# end
end
# GET /users/:id.:format
def show
# authorize! :read, @user
end
# GET /users/:id/edit
def edit
# authorize! :update, @user
end
# PATCH/PUT /users/:id.:format
def update
# authorize! :update, @user
respond_to do |format|
if @user.update(user_params)
sign_in(@user == current_user ? @user : current_user, :bypass => true)
format.html { redirect_to @user, notice: 'Your profile was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: @user.errors, status: :unprocessable_entity }
end
end
end
# GET/PATCH /users/:id/finish_signup
def finish_signup
# authorize! :update, @user
if request.patch? && params[:user] #&& params[:user][:email]
if @user.update(user_params)
@user.skip_reconfirmation!
# sign_in(@user, :bypass => true)
# redirect_to root_path, notice: 'Your profile was successfully updated.'
# redirect_to [@user, @user.profile || @user.build_profile]
sign_in_and_redirect(@user, :bypass => true)
else
@show_errors = true
end
end
end
# DELETE /users/:id.:format
def destroy
# authorize! :delete, @user
@user.destroy
respond_to do |format|
format.html { redirect_to root_url }
format.json { head :no_content }
end
end
private
def set_user
@user = User.find(params[:id])
end
def user_params
# params.require(:user).permit(policy(@user).permitted_attributes)
accessible = [ :first_name, :last_name, :email, :avatar ] # extend with your own params
accessible << [ :password, :password_confirmation ] unless params[:user][:password].blank?
# accessible << [:approved] if user.admin
params.require(:user).permit(accessible)
end
end
omniauth 回调 Controller
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def self.provides_callback_for(provider)
class_eval %Q{
def #{provider}
@user = User.find_for_oauth(env["omniauth.auth"], current_user)
if @user.persisted?
sign_in_and_redirect @user, event: :authentication
set_flash_message(:notice, :success, kind: "#{provider}".capitalize) if is_navigational_format?
else
session["devise.#{provider}_data"] = env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
}
end
# , current_user has been deleted from the end of line 51
#come back to put current_user into fidn by oauth so i can link other accounts - i have added this back for the purpose of solving the current problem
# puts current_user.inspect
# sign_in_and_redirect [@user, @user.profile || @user.build_profile]
# sign_in_and_redirect_user(:user, event: :authentication)
[:twitter, :facebook, :linkedin, :google_oauth2].each do |provider|
provides_callback_for provider
end
def after_sign_in_path_for(resource)
if resource.email_verified?
super resource
else
finish_signup_path(resource)
end
end
end
注册 Controller
class Users::RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
profile_path(resource)
end
private
def user_params
params.require(:user).permit(:first_name, :last_name, :email, :password )
end
end
身份.rb
class Identity < ActiveRecord::Base
belongs_to :user
validates_presence_of :uid, :provider
validates_uniqueness_of :uid, :scope => :provider
def self.find_for_oauth(auth)
find_or_create_by(uid: auth.uid, provider: auth.provider)
end
end
身份 Controller
class IdentitiesController < ApplicationController
before_action :set_identity, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
# GET /identities
# GET /identities.json
def index
@identities = Identity.all
end
# GET /identities/1
# GET /identities/1.json
def show
end
# GET /identities/new
def new
@identity = Identity.new
end
# GET /identities/1/edit
def edit
end
# POST /identities
# POST /identities.json
def create
@identity = Identity.new(identity_params)
respond_to do |format|
if @identity.save
format.html { redirect_to @identity, notice: 'Identity was successfully created.' }
format.json { render :show, status: :created, location: @identity }
else
format.html { render :new }
format.json { render json: @identity.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /identities/1
# PATCH/PUT /identities/1.json
def update
respond_to do |format|
if @identity.update(identity_params)
format.html { redirect_to @identity, notice: 'Identity was successfully updated.' }
format.json { render :show, status: :ok, location: @identity }
else
format.html { render :edit }
format.json { render json: @identity.errors, status: :unprocessable_entity }
end
end
end
# DELETE /identities/1
# DELETE /identities/1.json
def destroy
@identity.destroy
respond_to do |format|
format.html { redirect_to identities_url, notice: 'Identity was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_identity
@identity = Identity.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def identity_params
params[:identity]
end
end
设计邮件程序 - 确认
<div class="intpol3"><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></div>
当前问题总结:
在开发模式下:确认 token 的链接存在问题。我找不到任何 Material 表明为什么会出现这种情况。错误是:(ActionView::Template::Error (未定义方法 `match' for {:host=>"localhost", :port=>3000}:Hash):
在生产模式下,用户查找个人资料 ID 时出错。错误消息为: ActionView::Template::Error (没有路由匹配 {:action=>"show", :controller=>"profiles", :id=>nil} 缺少必需的键: [:id]):
我的个人资料路线是:
resources :profiles, only: [:show, :edit, :update, :destroy]
resources :users do
resources :profiles, only: [:new, :create]
end
所做的事情与教程中所示的不同:
我还允许电子邮件注册
我在用户 Controller 中的操作之前将“finish_sign_up”添加到 set_user
我添加了 g+ 策略(这意味着我的 gem 略有不同)
我的新用户方法不使用原始信息。它使用 oauth 处理过的信息。
我在完成注册方法中的重定向略有不同,尽管我已经对此进行了评论并返回到教程中规定的方式以尝试使其正常工作(尽管上述问题是重复)。
我正在疯狂地尝试解决这些问题。我想说三年对于这个问题来说太长了。如果有人能提供帮助,我会支付 10 倍,然后再支付一些。谢谢。
最佳答案
<div class="intpol3"><%= link_to 'Confirm my account',
confirmation_url(@resource, confirmation_token: @token) %></div>
尝试resource
而不是@resource
。 AFAIK 它只是一个 helper_method,而不是一个实例变量。
我认为这将完全解决您在生产中的问题。由于 @resource
与 resource
不同,因此尚未设置,您基本上是在调用 confirmation_url(nil,confirmation_token: @token)
,并且 nil
被传递到错误消息。
在开发过程中,似乎存在一个额外的问题,这很可能与您在 config/environments/development.rb< 中配置
最有可能的是在 ActionDispatch::Http::Url.build_host_url 中引发异常。我怀疑你有类似的东西:config.action_mailer.default_url_options
的方式有关
config.action_mailer.default_url_options[:host] = { host: 'localhost', port: 9000 }
将其更改为:
config.action_mailer.default_url_options[:host] = 'localhost:9000'
看看这是否能解决所有问题。如果我对 config.action_mailer.default_url_options
的配置方式有误,请粘贴您的 config/environments/development.rb
以及开发错误中的完整堆栈跟踪,以便我们可以进一步帮助您。
关于ruby-on-rails - Rails 4 - Devise Omniauth(多种策略),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34673116/
我已经将 gitlab 全部设置好并准备好omniauth,我想知道是否可以完全禁用使用密码和用户名的默认身份验证并仅使用omniauth(在我们的例子中为google登录)。我希望通过将 Googl
我是 Rails 和 Omniauth 的新手,所以提前为愚蠢的人感到抱歉 题。 我正在尝试为 Deezer 网站制定 Omniauth 策略。 http://www.deezer.com/en/de
所以我试图让 omniauth-facebook 在我的生产环境中工作。它使用 POW 在我的机器上本地运行良好。 我的产品环境是带有 nginx/unicorn 的 ubuntu,代码是 Rails
嗨,我正在学习如何使用omniauth 作为 ember 应用程序的后端。 当我运行我的应用程序时,我得到下面提到的错误 OmniAuth::NoSessionError - 您必须提供 sessio
我正在使用: Ruby on Rails 4 设计 3.0.3 omniauth (1.1.4) omniauth-facebook (1.4.1) omniauth-twitter (1.0.0)
如果我使用 omniauth 进行 Twitter 验证.. 下面的代码是 def create user = User.from_omniauth(env["omniauth.auth"])
再具体一点: 如果我打电话,我的 Rails 应用程序运行良好 /auth/facebook/callback或 /auth/facebook/callback?format=json 但是当我尝试打
在我的项目中,我有两类用户:求职者和招聘经理。求职者没有模型,他们只能使用从第三方供应商处收到的数据申请工作,同时通过 Omniauth 进行身份验证。招聘经理的信息存储在设计用户模型中。招聘经理还必
我正在尝试在 Rails 3.2.9 中使用 omniauth-facebook 登录 Facebook;我遵循了 Ryan Bates 在 http://railscasts.com/episode
我一直在探索我的 Rails 应用程序的身份验证选项。我需要用户名/密码身份验证以及将用户与其 Facebook、Twitter、Foursquare 等身份链接的选项。我通常会发现人们为此目的使用
关于如何记住我与 Omniauth 一起工作似乎有些困惑。 根据这个wiki ,您需要在 OmniauthCallbacksController 中包含以下内容: remember_me(user)
说我有用户和项目模型。用户和项目与HABTM相关。我的设置实际上比这要复杂一些,但是出于我的问题,我认为这可以做到。 现在,我想使用omniauth通过Twitter,Facebook来验证特定项目,
我正在尝试使用 omniauth 测试一个简单的 facebook 登录。但是,收到一条错误消息,指出“auth”未定义 variable 或 method。 omniauth 测试文档不包含 fac
我在 Twitter 上使用 gem。回调时,检查用户是否存在并创建他或将他发送回主页。 我可能做错了什么,但在我的回调代码中, request.env['omniauth.origin'] 为零 .
我将 OmniAuth 与 Devise 结合使用,以允许用户使用 facebook 登录或使用用户名和密码创建普通帐户。当我最初设置它时,我使用了来自 Railscasts 的优秀指导。 .在 2
我在端口 3101 上运行了一个 Rails 应用程序我通过 Apache 反向代理设置(就像 Phusion 在 this blog post 上建议的那样)将它提供给互联网。 我正在使用 Devi
我正在开发一个 Rails 3.0 应用程序并使用 OmniAuth + Identity 来验证注册。我已经实现了一个通过外键与身份模型相关联的用户模型,并且一切运行良好。现在,我想实现一个忘记密码
我有一个 Rails 应用程序设置为 OAuth2 提供程序(使用 Doorkeeper)。该应用程序为每个用户帐户使用不同的子域(或通过 cname 记录使用完全不同的域) i.e. user1.m
我正在使用 omniauth和 omniauth-identity用于通过 Google、Facebook 和传统用户名/密码进行身份验证。除了身份验证失败的情况外,我的所有工作都很好。失败时,例如输
我正在构建一个网站,并添加了“使用 Slack 登录”按钮。 我正在使用 omniauth-slack(最新的 8b2371),它运行良好。 但我只想允许来自我自己的 Slack 团队的用户。 有te
我是一名优秀的程序员,十分优秀!