devise
gemを使用しています。確認リンクをクリックした後、直接サインインします。現在、再度サインインするよう求めています。
最近、私はdevise初期化ファイルに以下を追加しました:
config.allow_insecure_token_lookup = true
config.secret_key = 'a8d814803c0bcc735ce657adc77793459d00154cdd7532c13d3489600dc4e963f86e14beb593a32cbe9dbbe9197c9ce50a30102f363d90350052dc8d69930033'
助言がありますか?
以前のバージョンのDeviseでは、ユーザーは確認後に自動的にサインインしていました。これは、確認の電子メールにアクセスできるすべてのユーザーが、リンクをクリックするだけで誰かのアカウントにサインインできることを意味しました。
ユーザーを自動的にサインインさせることも、電子メールの再確認ワークフローに悪影響を及ぼす可能性があります。ユーザーが自分の電子メールアドレスを変更することを決定し、その間に、新しい電子メールアドレスにタイプミスをしたとします。電子メールは別のアドレスに送信され、トークンを入手すると、そのアカウントにサインインできます。
ユーザーが電子メールをすぐに修正しても、害はありません。しかし、そうでない場合、他の誰かがそのアカウントにサインインする可能性があり、ユーザーはそれが発生したことを知りません。
このために、 Devise 3.1
確認後にユーザーを自動的にサインインしなくなりました。 config/initializers/devise.rbで以下を設定することにより、アップグレード後に古い動作を一時的に戻すことができます。
config.allow_insecure_sign_in_after_confirmation = true
このオプションは、移行を支援するために一時的にのみ使用できます。
config.allow_insecure_sign_in_after_confirmation
フラグはDeviseではサポートされなくなりました。
ユーザーが自分のアカウントを確認したときに自動的にログインすることで起こり得るセキュリティ上の懸念に注意する必要があります( http://blog.plataformatec.com.br/2013/08/devise-3-1-now-with -more-secure-defaults / )。一部のアプリでは、ユーザーエクスペリエンスの面でのメリットはセキュリティのトレードオフに値する場合があります。
結局のところ、セキュリティ上のリスクとは、a)ユーザーがメールアドレスを間違って入力した、b)ミスをすぐに修正しない、c)入力したメールが有効で機能するメールに対応している、d)誤って受信した人メールはそれを開き、リンクをクリックします。
これがアプリケーションにとって許容できるリスクプロファイルである場合は、デバイスのConfirmationsControllerをオーバーライドできます。
class ConfirmationsController < Devise::ConfirmationsController
def show
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
yield resource if block_given?
if resource.errors.empty?
set_flash_message(:notice, :confirmed) if is_flashing_format?
sign_in(resource) # <= THIS LINE ADDED
respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
else
respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render :new }
end
end
end
routes.rb
:
devise_for :users, controllers: { confirmations: 'confirmations' }
Deviseの最新バージョンでは、次のことができます。
config/routes.rb:
devise_for :users, controllers: { confirmations: 'users/confirmations' }
app/controllers/users/confirmations_controller.rb:
class Users::ConfirmationsController < Devise::ConfirmationsController
def show
super do |resource|
sign_in(resource)
end
end
end
Mb21の答えを見ると、
def show
super do |resource|
if resource.confirmation_sent_at > DateTime.now-2.hours && resource.errors.empty?
sign_in(resource)
end
end
end
confirm_sent_atは、メールがユーザーに送信された時刻です。これは、confirmed_atとは対照的です。これは、ユーザーがリンクをクリックした瞬間であり、サーバー上で常に2時間以内に発生します。
ユーザーが作成してから2時間以内にメール内のリンクをクリックした場合、ユーザーが自動的にサインインするようにしたかったので、 @Sjorの回答に基づいて、私たちは次のように行きました:
class ConfirmationsController < Devise::ConfirmationsController
def show
super do |resource|
if resource.confirmed_at > DateTime.now-2.hours && resource.errors.empty?
sign_in(resource)
end
end
end
end
ここには、それを解決する方法があります。
このコードにより、ユーザーは確認後に初めて自分のアカウントを確認する場合にのみ、自動的にサインインできます。
class ConfirmationsController < Devise::ConfirmationsController
before_action :maybe_auto_sign_in, only: :show
protected
def after_confirmation_path_for(resource_name, resource)
sign_in(resource) if @auto_sign_in
super
end
private
# Automatically sign in the user that confirmed his/her email first time.
def maybe_auto_sign_in
@auto_sign_in =
User.first_time_confirming?(params[:confirmation_token])
end
end
class User < ActiveRecord::Base
def self.first_time_confirming?(confirmation_token)
confirmation_token &&
User.where(confirmation_token: confirmation_token, unconfirmed_email: nil)
.exists?
end
end