会话劫持OmniAuth

时间:2015-04-18 05:42:15

标签: ruby-on-rails ruby facebook oauth omniauth

我在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

0 个答案:

没有答案