为登录用户设计忘记密码 [英] Devise Forgot Password for logged in user

查看:16
本文介绍了为登录用户设计忘记密码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否有一种方法可以在不强制用户注销的情况下调用忘记密码"程序

我遇到的情况是:1.用户使用facebook登录,为他们生成一个假密码2. 然后用户想要更改他们的电子邮件/姓名/密码,或者只是使用非 Facebook 登录

由于设计需要密码来更改这些字段,因此用户无法修改它们

我曾想过不强制设置密码,但这在安全方面没有意义,所以我只是将字段显示为文本并通知用户遵循忘记密码"程序以设置一个密码,然后他们可以更改字段

问题是我不能简单地从用户个人资料链接到这个,因为设计会告诉用户他们在已经登录的情况下不能这样做.

那么是否有一种方法可以覆盖忘记的密码或/users/password/edit 方法,以便登录用户也可以执行此操作?

解决方案

我在这里的完整解决方案,因为我当时还了解到用户在单击电子邮件中的链接后必须注销,是添加一些额外的 UserController实际编辑密码以及保存密码的操作.这不是一个理想的解决方案,冷可能以更好的方式完成,但它对我有用.

用户控制器;添加了重置方法

 before_filter :authenticate_user!, :except =>[:do_reset_password, :reset_password_edit]def reset_passwordid = 参数[:id]如果id.nil?id = current_user.id结尾if (!user_signed_in? || current_user.id.to_s != id.to_s)flash[:alert] = "你没有那个权利."redirect_to '/home'返回结尾@user = User.find(id)@user.send_reset_password_instructionsresponse_to do |格式|format.html { redirect_to '/users/edit', notice: '您将在几分钟内收到一封电子邮件,其中包含有关如何重置密码的说明.}结尾结尾def do_reset_passwordid = 参数[:id]如果id.nil?&&!current_user.nil?id = current_user.id结尾如果id.nil?@user = User.where(:reset_password_token => params[:user][:reset_password_token]).first别的@user = User.find(id)结尾如果@user.nil?||@user.reset_password_token.to_s != params[:user][:reset_password_token]flash[:alert] = "要重置的 URL 不正确,请重新发送重置电子邮件."redirect_to '/home'返回结尾# 可能有更好的方法,devise 应该能够给我们这些信息if params[:user][:password] != params[:user][:password_confirmation]flash[:alert] = "密码必须匹配."重定向到:返回返回结尾if @user.reset_password!(params[:user][:password],params[:user][:password_confirmation])@user.hasSetPassword = true@user.saveresponse_to do |格式|format.html { redirect_to '/home', notice: '您的密码已更改.'}结尾别的flash[:alert] = "密码无效,必须至少 6 个字符."重定向到:返回结尾结尾def reset_password_edit@user = User.where(:reset_password_token => params[:reset_password_token]).first如果@user.nil?||!@user.reset_password_period_valid?flash[:alert] = "密码重置期已过,请重新发送重置邮件"重定向到/home"返回结尾结尾

查看/设计/注册/编辑;将视图更改为不允许用户编辑需要密码的字段

 <%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f|%><%= devise_error_messages!%><% if !resource.hasSetPassword %><%= f.label :name %><br/><p style="line-height:24px;"><b><%= @user.name %></b></p><div><%= f.label :email %><br/><p style="line-height:24px;"><b><%=@user.email %></b></p><p style="position:relative; left:150px; width:420px;"><i>您无法更改任何设置,因为您尚未设置密码 <br/>您可以按照 </i><%= link_to "忘记密码", "/users/reset_password" %><我>程序</p>

<%其他%><p><%= f.label :name%><br/><%= f.text_field :name %></p><div><%= f.label :email %><br/><%= f.email_field :email %></div><div><%= f.label :password %><br/><%= f.password_field :password %><i>(如果您不想更改,请留空)</i></div><div><%= f.label :password_confirmation %><br/><%= f.password_field :password_confirmation %></div><div><%= f.label :current_password %><br/><%= f.password_field :current_password %><i>(我们需要您当前的密码来确认您的更改)</i>

<div><%= f.submit更新"%></div><%结束%><%结束%>

views/devise/mailer/reset_password_instructions;在我们的新案例中,必须将其更改为指向正确的 URL

 

你好 <%= @resource.email %>!

<p>有人请求了一个链接来更改您的密码,您可以通过下面的链接完成此操作.</p><% if !@resource.hasSetPassword %><p><%= link_to '更改我的密码', 'http://streetsbehind.me/users/reset_password_edit?reset_password_token='+@resource.reset_password_token %></p><!-- 待办事项:可能有比硬编码 streetbehind.me 更好的方法--><%其他%><p><%= link_to '更改我的密码', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token) %></p><%结束%><p>如果您没有提出要求,请忽略此电子邮件.</p><p>在您访问上面的链接并创建新密码之前,您的密码不会更改.</p>

views/users/reset_password_edit.erb

<%= form_for(@user, :url => url_for(:action => :do_reset_password) , :html => { :method => :post }) do |f|%><%= f.hidden_​​field :reset_password_token %><div><%= f.label :password, "新密码" %><br/><%= f.password_field :password %></div><div><%= f.label :password_confirmation, "确认新密码" %><br/><%= f.password_field :password_confirmation %></div><div><%= f.submit "更改我的密码" %></div><%结束%>

config/routes.rb

获取用户/重置密码"得到用户/reset_password_edit"资源:用户做发布do_reset_password"结尾

I'm wondering if there is a manner of calling the 'forgot password' procedure without forcing my user to log out

The case I'm running into is: 1. a user logs in with facebook, a fake password is generated for them 2. the user then wants to change their email/name/password, or just use non facebook login

since devise requires a password to change these fields, as it should, the user is unable to modify them

I had thought about just not forcing the password to be set but that doesn't make sense security wise so instead I just display the fields as text and notify the user to follow the 'forgot password' procedure in order to set a password and then they can change the fields

The issue then is that I cannot simply link to this from the user profile since devise will tell the user that they can't do this while already logged in.

So is there a manner of overriding the forgot password or /users/password/edit method so that a logged in user can perform this action as well?

解决方案

My complete solution here, because I then also learned that the user would have to log out after clicking the link in the email, was to add an some additional UserController actions for actually editing the password as well as saving it. This is not an ideal solution and cold probably be done in a better manner but it works for me.

users controller; added methods to do the reset

    before_filter :authenticate_user!, :except => [:do_reset_password, :reset_password_edit]

    def reset_password
        id = params[:id]
        if id.nil?
          id = current_user.id
        end    
        if (!user_signed_in? || current_user.id.to_s != id.to_s)
        flash[:alert] = "You don't have that right." 
          redirect_to '/home'
          return
        end

        @user = User.find(id)
        @user.send_reset_password_instructions

        respond_to do |format|
            format.html { redirect_to '/users/edit', notice: 'You will receive an email with instructions about how to reset your password in a few minutes.' }
        end
     end


    def do_reset_password
        id = params[:id]
        if id.nil? && !current_user.nil?
          id = current_user.id
        end

        if id.nil?
            @user = User.where(:reset_password_token => params[:user][:reset_password_token]).first
        else
            @user = User.find(id)
        end
        if  @user.nil? || @user.reset_password_token.to_s != params[:user][:reset_password_token]
          flash[:alert] = "Url to reset was incorrect, please resend reset email." 
          redirect_to '/home'
          return
        end

        # there may be a better way of doing this, devise should be able to give us these messages
        if params[:user][:password] != params[:user][:password_confirmation]
            flash[:alert] = "Passwords must match." 
              redirect_to :back
              return
        end
        if @user.reset_password!(params[:user][:password],params[:user][:password_confirmation])
            @user.hasSetPassword = true
            @user.save
            respond_to do |format|
                format.html { redirect_to '/home', notice: 'Your password has been changed.' }
            end
        else
            flash[:alert] = "Invalid password, must be at least 6 charactors." 
              redirect_to :back 
        end
    end

    def reset_password_edit
        @user = User.where(:reset_password_token => params[:reset_password_token]).first
        if  @user.nil? || !@user.reset_password_period_valid?
            flash[:alert] = "Password reset period expired, please resend reset email" 
            redirect_to "/home"
            return
        end
    end

views/devise/registrations/edit; changed the view to not let the user edit fields that require a password

    <%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
      <%= devise_error_messages! %>

      <% if !resource.hasSetPassword %>                                           
          <%= f.label :name %><br />
          <p style="line-height:24px;"><b><%= @user.name %></b></p>             
          <div><%= f.label :email %><br />
              <p style="line-height:24px;"><b><%= @user.email %> </b></p>
              <p style="position:relative; left:150px; width:420px;">
                <i>you cannot change any settings because you have not set a password <br />yet, you can do so by following the </i>
                <%= link_to "Forgot your password", "/users/reset_password" %> <i> procedure</i>
              </p>
          </div>
      <% else %>                      
          <p><%= f.label :name %><br />
          <%= f.text_field :name %></p>         
          <div><%= f.label :email %><br />
          <%= f.email_field :email %></div>

          <div><%= f.label :password %> <br />
          <%= f.password_field :password %><i>(leave blank if you don't want to change it)</i></div>

          <div><%= f.label :password_confirmation %><br />
          <%= f.password_field :password_confirmation %></div>

          <div><%= f.label :current_password %> <br />
          <%= f.password_field :current_password %>
          <i>(we need your current password to confirm your changes)</i>
          </div>
        <div><%= f.submit "Update" %></div>
      <% end %>
    <% end %>

views/devise/mailer/reset_password_instructions; had to change it to point to the right URL in our new case

    <p>Hello <%= @resource.email %>!</p>

    <p>Someone has requested a link to change your password, and you can do this through the link below.</p>

    <% if !@resource.hasSetPassword %>
        <p><%= link_to 'Change my password', 'http://streetsbehind.me/users/reset_password_edit?reset_password_token='+@resource.reset_password_token %></p>
    <!-- todo: there's probably a better way of doing this than just hardcoding streetsbehind.me -->
    <% else %>
        <p><%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token) %></p>
    <% end %>
    <p>If you didn't request this, please ignore this email.</p>
    <p>Your password won't change until you access the link above and create a new one.</p>

views/users/reset_password_edit.erb

<%= form_for(@user, :url => url_for(:action => :do_reset_password) , :html => { :method => :post }) do |f| %>

  <%= f.hidden_field :reset_password_token %>

  <div><%= f.label :password, "New password" %><br />
  <%= f.password_field :password %></div>

  <div><%= f.label :password_confirmation, "Confirm new password" %><br />
  <%= f.password_field :password_confirmation %></div>

  <div><%= f.submit "Change my password" %></div>
<% end %>

config/routes.rb

get "users/reset_password"
get "users/reset_password_edit"

resource :users do
  post 'do_reset_password'
end

这篇关于为登录用户设计忘记密码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆