我在Ruby on Rails4上使用OmniAuth。 但有些用户报告,当他使用OmniAuth登录时,hee可以是其他用户,比如会话劫持。
我不确定我的代码是否有问题...... 此代码的目的是用户可以使用一个帐户登录facebook twitter和电子邮件。
当用户未提供电子邮件地址时,电子邮件将为random@example.com
用户可以从registrations_controller中删除社交记录
这是我的代码。
omniauth_callbacks_controller.rb
<pre>class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
if user_signed_in?
user = User.find(current_user.id)
social = Social.find_by(user_id: current_user.id, provider: "facebook")
unless social
social = Social.new(
uid: request.env["omniauth.auth"].uid,
username: request.env["omniauth.auth"].extra.raw_info.name, #facebook username
provider: request.env["omniauth.auth"].provider,
token: request.env["omniauth.auth"].credentials.token
)
begin
user.socials << social
rescue
flash[:danger] = t("messages.error")
else
ensure
redirect_to user_path
end
end
else
social = Social.find_by(:provider => request.env["omniauth.auth"].provider, :uid => request.env["omniauth.auth"].uid)
if social
user = User.find(social.user_id)
if user
set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
flash["facebook"] = true
sign_in_and_redirect user, :event => :authentication
else
redirect_to root_path
end
else
if request.env["omniauth.auth"].info.email.present?
email = request.env["omniauth.auth"].info.email
user = User.find_by_email(request.env["omniauth.auth"].info.email)
else
email = User.create_unique_email
end
unless user
user = User.create(
email: email,
confirmation_token: nil,
confirmed_at: Time.now
)
end
social = Social.new(
uid: request.env["omniauth.auth"].uid,
username: request.env["omniauth.auth"].extra.raw_info.name,
provider: request.env["omniauth.auth"].provider,
token: request.env["omniauth.auth"].credentials.token
)
user.socials << social
set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
flash["facebook"] = true
sign_in_and_redirect user, :event => :authentication
end
end
end
def twitter
if user_signed_in?
user = User.find(current_user.id)
social = Social.find_by(user_id: current_user.id, provider: "twitter")
unless social
social = Social.new(
username: request.env["omniauth.auth"].info.nickname,
provider: request.env["omniauth.auth"].provider,
uid: request.env["omniauth.auth"].uid,
token: request.env["omniauth.auth"].credentials.token,
secret: request.env["omniauth.auth"].credentials.secret
)
begin
user.socials << social
rescue
flash[:danger] = t("messages.error")
else
ensure
redirect_to user_path
end
end
else
social = Social.find_by(:provider => request.env["omniauth.auth"].provider, :uid => request.env["omniauth.auth"].uid)
if social
user = User.find(social.user_id)
if user
set_flash_message(:notice, :success, :kind => "Twitter") if is_navigational_format?
flash["twitter"] = true
sign_in_and_redirect user, :event => :authentication
else
redirect_to user_path
end
else
user = User.create(
email: User.create_unique_email,
confirmation_token: nil,
confirmed_at: Time.now
)
social = Social.new(
username: request.env["omniauth.auth"].info.nickname,
provider: request.env["omniauth.auth"].provider,
uid: request.env["omniauth.auth"].uid,
token: request.env["omniauth.auth"].credentials.token,
secret: request.env["omniauth.auth"].credentials.secret
)
user.socials << social
set_flash_message(:notice, :success, :kind => "Twitter") if is_navigational_format?
flash["twitter"] = true
sign_in_and_redirect user, :event => :authentication
end
end
end
private
def sign_in_and_redirect(resource_or_scope, *args)
options = args.extract_options!
scope = Devise::Mapping.find_scope!(resource_or_scope)
resource = args.last || resource_or_scope
sign_in(scope, resource, options)
redirect_to user_path
end
端
架构是这个
create_table "socials", force: true do |t|
t.integer "user_id"
t.string "uid", default: "", null: false
t.string "provider", default: "", null: false
t.string "username"
t.string "token"
t.datetime "created_at"
t.datetime "updated_at"
t.string "secret"
end
create_table "users", force: true do |t|
t.string "email", default: ""
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.string "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.string "unconfirmed_email"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
registrations_controller.rb
def remove_social
begin
if current_user.email.blank? || current_user.encrypted_password.blank?
raise t("messages.error")
end
if current_user.unconfirmed_email.present?
raise t("messages.error")
end
if /example.com/ =~ current_user.email
raise t("messages.error")
end
social = Social.where(user_id: current_user.id, provider: params[:social]).first
if social.destroy
flash[:success] = t("messages.success")
else
raise flash[:danger] = t("messages.error")
end
rescue => e
flash[:danger] = e.message
else
flash[:success] = t("messages.success")
ensure
redirect_to root_path
end
端