设计确认电子邮件将发送到邮件,如果用户未确认邮件,如何防止用户登录?

时间:2019-05-30 14:03:10

标签: ruby-on-rails ruby devise

我正在使用装置。 在没有电子邮件确认的情况下登录之前。 然后,我必须为我的申请设置电子邮件确认。 因此,我在user.rb上添加了Confirmable,并对设计用户迁移进行了更改。 另外,我对devise.rb文件进行了更改。 另外,我在config / environment / development.rb文件中将邮件设置为smtp。

我认为对于邮递员来说设置是正确的,但是问题是: 当用户注册为新用户时,带有确认令牌的邮件将发送给该​​用户。但是,即使不单击该邮件链接,用户也可以登录。 如果用户无需确认令牌即可登录,邮件设置的用途是什么? 如果他们不验证邮件确认令牌,如何防止用户登录?
我已经厌倦了制作定制的可确认控制器,但是结果是相同的。

application_controller.rb

const foo = {
    a: {
        a1: 'a1',
        a2: 'a2',
    },
    b: 'b',
};

(() => {
    const bar1 = { ...foo };
    bar1.a.a1 = 'changed';
})();

console.log(foo);

authorization_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

users_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

registrations_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

user.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

2 个答案:

答案 0 :(得分:1)

看一下设计初始化器,您需要将allow_unconfirmed_access_for设置为0(实际上,默认情况下应为零)。根据{{​​3}}:

#   * +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正在使用此devise documentation来验证未经确认的访问。

您还可以发布此方法的结果吗?

  • 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?

答案 1 :(得分:0)

以上代码的逻辑没有任何错误。 我在查看哪个路由生成链接的视图上有误。

正确的网址是:

<p>
   <%= link_to 'Confirm my account', confirmation_url(@resource,
   confirmation_token: @token) %>
</p>