Devise重置密码通知:如何通过SMS而非邮件发送至手机号
解决Devise框架下用SMS发送重置密码通知的方案
嘿,这个需求我之前在做一个无邮箱注册的项目时刚好踩过坑,给你整理一套可行的方案,完全适配你的场景——用户无邮箱、手机号必填:
1. 换掉Devise默认的密码重置控制器
Devise自带的PasswordsController是硬绑邮箱逻辑的,咱们得自己写一个控制器继承它,把查找用户的逻辑改成按手机号来:
# app/controllers/users/passwords_controller.rb class Users::PasswordsController < Devise::PasswordsController def create # 按手机号查找用户,替代默认的邮箱查找逻辑 @user = User.find_by(phone_number: params[:user][:phone_number]) if @user.present? # 调用Devise内置方法生成重置令牌,同时触发咱们后面重写的通知逻辑 @user.send_reset_password_instructions flash[:notice] = "重置密码的验证码已发送到你的手机号,15分钟内有效哦" else flash[:alert] = "没找到这个手机号对应的用户,请检查输入" end redirect_to new_user_password_path end end
然后在路由里指定用咱们自定义的控制器:
# config/routes.rb devise_for :users, controllers: { passwords: 'users/passwords' }
2. 重写用户模型的重置通知方法
Devise默认会发邮件,咱们要把这个逻辑彻底换成发短信。在User模型里重写send_reset_password_instructions方法:
# app/models/user.rb class User < ApplicationRecord # 加上email_required: false,告诉Devise不强制要求邮箱字段 devise :database_authenticatable, :registerable, :recoverable, :validatable, email_required: false, email_verifiable: false # 手机号必填+唯一的验证规则 validates :phone_number, presence: true, uniqueness: true # 重写Devise的重置密码通知方法 def send_reset_password_instructions # 生成并保存重置密码令牌(Devise内置方法,不用自己造轮子) generate_reset_password_token! # 这里调用你的短信服务发送内容,把令牌传进去 # 示例:假设你有个封装好的SmsSender服务 SmsSender.send( self.phone_number, "你的密码重置验证码是:#{reset_password_token},请在15分钟内完成密码重置" ) end end
3. 调整前端视图,把邮箱输入换成手机号
原来的密码重置申请页是让用户输邮箱的,咱们要改成输手机号:
# app/views/devise/passwords/new.html.erb <h2>重置密码</h2> <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %> <%= devise_error_messages! %> <div class="field"> <%= f.label :phone_number, "手机号" %><br /> <%= f.text_field :phone_number, autofocus: true, placeholder: "请输入你的手机号" %> </div> <div class="actions"> <%= f.submit "发送重置短信" %> </div> <% end %> <%= render "devise/shared/links" %>
4. 一些细节注意点
- 短信服务集成:上面的
SmsSender是示例,你得换成自己实际用的短信服务商API(比如阿里云、腾讯云或者Twilio),记得加异常捕获处理发送失败的情况,给用户友好提示。 - 令牌有效期:可以在
config/initializers/devise.rb里调整config.reset_password_within = 15.minutes,和短信里的提示保持一致。 - Devise验证规则:一定要确认关掉邮箱相关的强制验证,不然用户无邮箱注册时会触发Devise的默认校验报错。
整个流程跑起来就是:用户输入手机号→系统生成唯一重置令牌→短信发送令牌→用户拿着令牌去输入新密码(Devise默认的密码重置编辑页可以直接用,只要输入令牌和新密码就行)。
内容的提问来源于stack exchange,提问作者Purry
相关产品推荐
相关产品推荐

