为登录用户设计忘记密码
我想知道是否有一种方式调用’忘记密码’程序而不强迫我的用户注销
我遇到的情况是:1。用户使用facebook登录,为他们生成假密码2.然后用户想要更改他们的电子邮件/名称/密码,或者只使用非Facebook登录
由于设计需要密码来更改这些字段,因此用户无法修改它们
我曾经考虑过不强制设置密码,但安全性没有意义,所以我只是将字段显示为文本并通知用户按照“忘记密码”程序设置密码然后他们可以改变领域
问题是我不能简单地从用户配置文件链接到这个,因为设计会告诉用户他们在登录时无法执行此操作。
那么是否有一种覆盖忘记密码或/ users / password / edit方法的方式,以便登录用户也可以执行此操作?
您无法重置密码的原因是因为设计尝试使用当前会话对用户进行身份validation,并且当成功时,您将自动重定向到它应该去的任何路径。 您需要的是覆盖密码控制器的编辑和更新操作,使其跳过此步骤。
这是代码。 在您的密码控制器中添加以下代码(您可以请设计为您生成控制器,或者您可以创建以下控制器)。 更新覆盖是必要的,否则登录用户将在重置密码后自动注销。 (或者,如果你希望它像你那样可以摆脱#update覆盖)
class PasswordsController < Devise::PasswordsController # here we need to skip the automatic authentication based on current session for the following two actions # edit: shows the reset password form. need to skip, otherwise it will go directly to root # update: updates the password, need to skip otherwise it won't even reset if already logged in skip_before_filter :require_no_authentication, :only => [:edit, :update] # we need to override the update, too. # After a password is reset, all outstanding sessions are gone. # When already logged in, sign_in is a no op, so the session will expire, too. # The solution is to logout and then re-login which will make the session right. def update super if resource.errors.empty? sign_out(resource_name) sign_in(resource_name, resource) end end end
路线如下
# config/routes.rb devise_for :users, :controllers => {:passwords => 'passwords'}
您可以使用@user.send_reset_password_instructions
生成密码重置令牌并发送电子邮件。 如果您只是直接调用邮件程序,则不会生成密码重置令牌来validation重置。
我在这里完整的解决方案,因为我还了解到用户在点击电子邮件中的链接后必须注销,就是添加一些额外的UserController操作来实际编辑密码并保存密码。 这不是一个理想的解决方案,冷却可能以更好的方式完成,但它适用于我。
用户控制器; 添加了重置方法
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
意见/设计/注册/编辑; 将视图更改为不让用户编辑需要密码的字段
<%= 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 %>
<%= @user.name %>
<%= f.label :email %>
<%= @user.email %>
you cannot change any settings because you have not set a password
yet, you can do so by following the <%= link_to "Forgot your password", "/users/reset_password" %> procedure
<% else %> <%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.email_field :email %> <%= f.label :password %>
<%= f.password_field :password %>(leave blank if you don't want to change it) <%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation %> <%= f.label :current_password %>
<%= f.password_field :current_password %> (we need your current password to confirm your changes) <%= f.submit "Update" %> <% end %> <% end %>
视图/设计/邮寄者/ reset_password_instructions; 在我们的新案例中,我必须将其更改为指向正确的URL
Hello <%= @resource.email %>!
Someone has requested a link to change your password, and you can do this through the link below.
<% if !@resource.hasSetPassword %> <%= link_to 'Change my password', 'http://streetsbehind.me/users/reset_password_edit?reset_password_token='+@resource.reset_password_token %>
<% else %> <%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token) %>
<% end %> If you didn't request this, please ignore this email.
Your password won't change until you access the link above and create a new one.
意见/用户/ 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 %> <%= f.label :password, "New password" %>
<%= f.password_field :password %> <%= f.label :password_confirmation, "Confirm new password" %>
<%= f.password_field :password_confirmation %> <%= f.submit "Change my password" %> <% end %>
配置/ routes.rb中
get "users/reset_password" get "users/reset_password_edit" resource :users do post 'do_reset_password' end
- 如何强制Rails ActiveRecord提交事务刷新
- 将局部变量传递给已加载视图后呈现的局部变量
- Rails 3获取原始发布数据并将其写入tmp文件
- rails 3 – 如何将PARTIAL呈现为Json响应
- 无效的路由名称,已在使用中:’admin_root’(ArgumentError) – ActiveAdmin安装失败
- 在Rails模型中是否应该避免使用任何“受保护”的名称?
- 为什么carrierwave导致NameError:未初始化的常量Micropost :: PictureUploader错误?
- after_save回调将updated_by列设置为current_user
- Javascript错误未知提供者:在Rails缩小Angularjs之后的tProvider < – t