设计确认电子邮件正在发送到邮件,如果用户不确认邮件,如何防止用户登录?
Devise Confirmation email is being to sent to mail, How to prevent user from login if they don't confirm mail?
我正在使用设计。
在我能够在没有电子邮件确认的情况下登录之前。
然后我必须为我的申请设置电子邮件确认。
因此,我在 user.rb 上添加了 confirmable,并对设计用户迁移进行了更改。
另外,我对 devise.rb 文件进行了更改。
我还在 config/environment/development.rb 文件上将邮件程序设置为 smtp。
我认为邮件程序的设置是正确的,但问题是:
当用户注册为新用户时,带有确认令牌的邮件将发送给该用户。但即使不单击该邮件 link 用户也可以登录。
如果用户可以在没有确认令牌的情况下登录,那么设置邮件程序有什么用?
如果用户不验证邮件确认令牌,如何防止用户登录?
我已经厌倦了制作定制的可确认控制器,但结果是一样的。
application_controller.rb
# frozen_string_literal: true
# Router entry point
require 'json_web_token'
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
before_action :make_action_mailer_use_request_host_and_protocol
# before_action :authenticate_user!, :set_mailer_host
protect_from_forgery with: :exception
respond_to :html, :json
def index
render template: 'application'
end
def not_found
render json: { error: 'not_found' }
end
def authorize_request
header = request.headers['Authorization']
header = header.split(' ').last if header
begin
@decoded = JsonWebToken.decode(header)
@current_user = User.find(@decoded[:user_id])
rescue ActiveRecord::RecordNotFound => e
render json: { errors: e.message }, status: :unauthorized
rescue JWT::DecodeError => e
render json: { errors: e.message }, status: :unauthorized
end
end
protected
def current_user
@current_user ||= User.find_by(id: session[:user_id])
end
def signed_in?
!!current_user
end
helper_method :current_user, :signed_in?
def current_user=(user)
session[:user_id] = user&.id
@current_user = user
end
def configure_permitted_parameters
update_attrs = [:password, :password_confirmation, :current_password]
devise_parameter_sanitizer.permit :account_update, keys: update_attrs
devise_parameter_sanitizer.permit(:login, keys: [ :email, :password ])
end
private
def make_action_mailer_use_request_host_and_protocol
ActionMailer::Base.default_url_options[:protocol] = request.protocol
ActionMailer::Base.default_url_options[:host] = request.host_with_port
end
end
authorization_controller.rb
module Api
module V1
class AuthenticationController < ApplicationController
skip_before_action :verify_authenticity_token
before_action :authorize_request, except: :login
# POST /auth/login
def login
@user = User.find_by_email(params[:email])
if @user&.valid_password?(params[:password])
token = JsonWebToken.encode(user_id: @user.id)
time = Time.now + 24.hours.to_i
render json: { token: token, exp: time.strftime("%m-%d-%Y %H:%M"),
username: @user.username, user_id: @user.id }, status: :ok
else
render json: { error: 'unauthorized' }, status: :unauthorized
end
end
private
def login_params
params.permit(:email, :password)
end
end
end
end
users_controller.rb
module Api
module V1
class UsersController < ApplicationController
skip_before_action :verify_authenticity_token
before_action :authorize_request, except: :create
# GET /users
def index
@users = User.all
render json: @users, status: :ok
end
def create
# render plain: params.inspect
@user = User.new(user_params)
# render plain: user_params.insp
if @user.save
render json: @user, status: :created
else
render json: { errors: @user.errors.full_messages },
status: :unprocessable_entity
end
end
def update
user = User.find(params[:id])
if user.update(user_params)
render json: user, status: :created
else
render json: { errors: user.errors.full_messages },
status: :unprocessable_entity
end
end
def show
user = User.find(params[:id])
if !user.nil?
render json: user, status: :ok
else
render json: {errors: user.errors.full_messages}, status: :unprocessable_entity
end
end
def destroy
user = User.find(params[:id])
if user.destroy
render json: {success: "deleted successfully"}, status: :ok
else
render json: {errors: user.errors.full_messages}, status: :not_acceptable
end
end
private
def find_user
@user = User.find_by_username!(params[:_username])
rescue ActiveRecord::RecordNotFound
render json: { errors: 'User not found' }, status: :not_found
end
def user_params
params.permit(
:first_name, :last_name, :username, :email, :password, :password_confirmation
)
end
end
end
end
registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
skip_before_action :require_no_authentication
def update_resource(resource, params)
if resource.encrypted_password.blank?
resource.email = params[:email] if params[:email]
if !params[:password].blank? && params[:password] == params[:password_confirmation]
resource.password = params[:password]
resource.save
end
if resource.valid?
resource.update_without_password(params)
end
else
resource.update_with_password(params)
end
end
end
user.rb
class User < ApplicationRecord
# has_secure_password
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable, :omniauthable, password_length: 8..36
has_many :identities
has_one :testimonials
has_many :questions
has_many :answers
def facebook
identities.where(provider: 'facebook').first
end
def facebook_client
@facebook_client ||= Facebook.client(access_token: facebook.accesstoken)
end
def twitter
identities.where(provider: 'twitter').first
end
def twitter_client
@twitter_client ||= Twitter.client(access_token: twitter.accesstoken)
end
def google_oauth2
identities.where(provider: 'google_oauth2').first
end
def google_oauth2_client
unless @google_oauth2_client
@google_oauth2_client = Google::APIClient.new(application_name: '',
application_version: '')
@google_oauth2_client.authorization.update_token!(access_token: google_oauth2.accesstoken,
refresh_token: google_oauth2.refreshtoken)
end
@google_oauth2_client
end
#validation for users
validates :username, presence: true, uniqueness: {case_sensitive: false}
# validates_format_of :username, with: /^[a-zA-Z0-9_\.]*$/, :multiline => true
validates :email, presence: true, uniqueness: {case_senstive: false}
PASSWORD_FORMAT = /\A
(?=.{8,}) # Must contain 8 or more characters
(?=.*\d) # Must contain a digit
(?=.*[a-z]) # Must contain a lower case character
(?=.*[A-Z]) # Must contain an upper case character
(?=.*[[:^alnum:]]) # Must contain a symbol
/x
validates :password,
presence: true,
# length: { in: Devise.password_length },
format: { with: PASSWORD_FORMAT, message: 'must contain 8 Characters with at least One Lowercase, One Uppercase, One Number and One Special Character' },
confirmation: true,
on: :create
validates :password_confirmation,
presence: true
validates :password,
# allow_nil: true,
# length: { in: Devise.password_length },
format: { with: PASSWORD_FORMAT, message: 'must contain 8 Characters with at least one Uppercase, One Number and One Special Character' },
confirmation: true,
on: :update
end
看看你的设计初始化器,你需要将 allow_unconfirmed_access_for
设置为 0(实际上,默认情况下它应该为零)。根据devise documentation:
# * +allow_unconfirmed_access_for+: the time you want to allow the user to access their account
# before confirming it. After this period, the user access is denied. You can
# use this to let your user access some features of your application without
# confirming the account, but blocking it after a certain period (ie 7 days).
# By default allow_unconfirmed_access_for is zero, it means users always have to confirm to sign in.
Devise 正在使用此 method 来验证未确认的访问。
你能不能也post这个方法的结果:
User.find(id_of_user_that_was_just_created).confirmation_required?
User.find(id_of_user_that_was_just_created).confirmed?
User.find(id_of_user_that_was_just_created).confirmation_period_valid?
以上代码逻辑没有任何错误。
我对路由生成 link.
的视图有误
正确的url是:
<p>
<%= link_to 'Confirm my account', confirmation_url(@resource,
confirmation_token: @token) %>
</p>
我正在使用设计。 在我能够在没有电子邮件确认的情况下登录之前。 然后我必须为我的申请设置电子邮件确认。 因此,我在 user.rb 上添加了 confirmable,并对设计用户迁移进行了更改。 另外,我对 devise.rb 文件进行了更改。 我还在 config/environment/development.rb 文件上将邮件程序设置为 smtp。
我认为邮件程序的设置是正确的,但问题是:
当用户注册为新用户时,带有确认令牌的邮件将发送给该用户。但即使不单击该邮件 link 用户也可以登录。
如果用户可以在没有确认令牌的情况下登录,那么设置邮件程序有什么用?
如果用户不验证邮件确认令牌,如何防止用户登录?
我已经厌倦了制作定制的可确认控制器,但结果是一样的。
application_controller.rb
# frozen_string_literal: true
# Router entry point
require 'json_web_token'
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
before_action :make_action_mailer_use_request_host_and_protocol
# before_action :authenticate_user!, :set_mailer_host
protect_from_forgery with: :exception
respond_to :html, :json
def index
render template: 'application'
end
def not_found
render json: { error: 'not_found' }
end
def authorize_request
header = request.headers['Authorization']
header = header.split(' ').last if header
begin
@decoded = JsonWebToken.decode(header)
@current_user = User.find(@decoded[:user_id])
rescue ActiveRecord::RecordNotFound => e
render json: { errors: e.message }, status: :unauthorized
rescue JWT::DecodeError => e
render json: { errors: e.message }, status: :unauthorized
end
end
protected
def current_user
@current_user ||= User.find_by(id: session[:user_id])
end
def signed_in?
!!current_user
end
helper_method :current_user, :signed_in?
def current_user=(user)
session[:user_id] = user&.id
@current_user = user
end
def configure_permitted_parameters
update_attrs = [:password, :password_confirmation, :current_password]
devise_parameter_sanitizer.permit :account_update, keys: update_attrs
devise_parameter_sanitizer.permit(:login, keys: [ :email, :password ])
end
private
def make_action_mailer_use_request_host_and_protocol
ActionMailer::Base.default_url_options[:protocol] = request.protocol
ActionMailer::Base.default_url_options[:host] = request.host_with_port
end
end
authorization_controller.rb
module Api
module V1
class AuthenticationController < ApplicationController
skip_before_action :verify_authenticity_token
before_action :authorize_request, except: :login
# POST /auth/login
def login
@user = User.find_by_email(params[:email])
if @user&.valid_password?(params[:password])
token = JsonWebToken.encode(user_id: @user.id)
time = Time.now + 24.hours.to_i
render json: { token: token, exp: time.strftime("%m-%d-%Y %H:%M"),
username: @user.username, user_id: @user.id }, status: :ok
else
render json: { error: 'unauthorized' }, status: :unauthorized
end
end
private
def login_params
params.permit(:email, :password)
end
end
end
end
users_controller.rb
module Api
module V1
class UsersController < ApplicationController
skip_before_action :verify_authenticity_token
before_action :authorize_request, except: :create
# GET /users
def index
@users = User.all
render json: @users, status: :ok
end
def create
# render plain: params.inspect
@user = User.new(user_params)
# render plain: user_params.insp
if @user.save
render json: @user, status: :created
else
render json: { errors: @user.errors.full_messages },
status: :unprocessable_entity
end
end
def update
user = User.find(params[:id])
if user.update(user_params)
render json: user, status: :created
else
render json: { errors: user.errors.full_messages },
status: :unprocessable_entity
end
end
def show
user = User.find(params[:id])
if !user.nil?
render json: user, status: :ok
else
render json: {errors: user.errors.full_messages}, status: :unprocessable_entity
end
end
def destroy
user = User.find(params[:id])
if user.destroy
render json: {success: "deleted successfully"}, status: :ok
else
render json: {errors: user.errors.full_messages}, status: :not_acceptable
end
end
private
def find_user
@user = User.find_by_username!(params[:_username])
rescue ActiveRecord::RecordNotFound
render json: { errors: 'User not found' }, status: :not_found
end
def user_params
params.permit(
:first_name, :last_name, :username, :email, :password, :password_confirmation
)
end
end
end
end
registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
skip_before_action :require_no_authentication
def update_resource(resource, params)
if resource.encrypted_password.blank?
resource.email = params[:email] if params[:email]
if !params[:password].blank? && params[:password] == params[:password_confirmation]
resource.password = params[:password]
resource.save
end
if resource.valid?
resource.update_without_password(params)
end
else
resource.update_with_password(params)
end
end
end
user.rb
class User < ApplicationRecord
# has_secure_password
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable, :omniauthable, password_length: 8..36
has_many :identities
has_one :testimonials
has_many :questions
has_many :answers
def facebook
identities.where(provider: 'facebook').first
end
def facebook_client
@facebook_client ||= Facebook.client(access_token: facebook.accesstoken)
end
def twitter
identities.where(provider: 'twitter').first
end
def twitter_client
@twitter_client ||= Twitter.client(access_token: twitter.accesstoken)
end
def google_oauth2
identities.where(provider: 'google_oauth2').first
end
def google_oauth2_client
unless @google_oauth2_client
@google_oauth2_client = Google::APIClient.new(application_name: '',
application_version: '')
@google_oauth2_client.authorization.update_token!(access_token: google_oauth2.accesstoken,
refresh_token: google_oauth2.refreshtoken)
end
@google_oauth2_client
end
#validation for users
validates :username, presence: true, uniqueness: {case_sensitive: false}
# validates_format_of :username, with: /^[a-zA-Z0-9_\.]*$/, :multiline => true
validates :email, presence: true, uniqueness: {case_senstive: false}
PASSWORD_FORMAT = /\A
(?=.{8,}) # Must contain 8 or more characters
(?=.*\d) # Must contain a digit
(?=.*[a-z]) # Must contain a lower case character
(?=.*[A-Z]) # Must contain an upper case character
(?=.*[[:^alnum:]]) # Must contain a symbol
/x
validates :password,
presence: true,
# length: { in: Devise.password_length },
format: { with: PASSWORD_FORMAT, message: 'must contain 8 Characters with at least One Lowercase, One Uppercase, One Number and One Special Character' },
confirmation: true,
on: :create
validates :password_confirmation,
presence: true
validates :password,
# allow_nil: true,
# length: { in: Devise.password_length },
format: { with: PASSWORD_FORMAT, message: 'must contain 8 Characters with at least one Uppercase, One Number and One Special Character' },
confirmation: true,
on: :update
end
看看你的设计初始化器,你需要将 allow_unconfirmed_access_for
设置为 0(实际上,默认情况下它应该为零)。根据devise documentation:
# * +allow_unconfirmed_access_for+: the time you want to allow the user to access their account # before confirming it. After this period, the user access is denied. You can # use this to let your user access some features of your application without # confirming the account, but blocking it after a certain period (ie 7 days). # By default allow_unconfirmed_access_for is zero, it means users always have to confirm to sign in.
Devise 正在使用此 method 来验证未确认的访问。
你能不能也post这个方法的结果:
User.find(id_of_user_that_was_just_created).confirmation_required?
User.find(id_of_user_that_was_just_created).confirmed?
User.find(id_of_user_that_was_just_created).confirmation_period_valid?
以上代码逻辑没有任何错误。 我对路由生成 link.
的视图有误正确的url是:
<p>
<%= link_to 'Confirm my account', confirmation_url(@resource,
confirmation_token: @token) %>
</p>