Devise重置密码邮件指向错误控制器,需保留Rails本地登录功能
解决Devise与Devise Token Auth共存时的密码重置链接问题
这个问题我之前也碰到过,核心是同时启用Devise的Web登录和Devise Token Auth的API登录时,两者的密码重置路由发生了优先级冲突,导致API请求触发的重置邮件错误使用了Web端的路由。下面给你两种可行的解决办法:
方法一:重写User模型的URL生成逻辑
这种方式可以根据请求来源自动切换重置链接,既保留Web端的正常功能,又确保API端生成正确的链接。
步骤1:修改User模型
在你的app/models/user.rb中添加重写方法:
class User < ApplicationRecord devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable include DeviseTokenAuth::Concerns::User # 重写重置密码URL生成方法 def reset_password_url(token, opts = {}) # 识别API请求(通过是否携带redirect_url参数判断) if opts[:redirect_url].present? # 使用API端的重置路由 edit_api_auth_password_url(reset_password_token: token, redirect_url: opts[:redirect_url]) else # Web端请求沿用Devise默认路由 super(token, opts) end end end
步骤2:保留原有路由配置
你的routes.rb不需要修改,继续保留两行配置:
devise_for :users namespace :api, defaults: {format: :json} do mount_devise_token_auth_for 'User', at: 'auth' end
方法二:自定义Devise Token Auth的邮件模板
如果你不想修改模型代码,也可以直接调整API端的邮件模板,强制使用API路由。
步骤1:生成Devise Token Auth的邮件视图文件
在终端执行以下命令,生成可自定义的邮件模板:
rails generate devise_token_auth:views
步骤2:修改重置密码邮件模板
找到生成的app/views/devise_token_auth/mailer/reset_password_instructions.html.erb(如果需要适配纯文本邮件,同时修改.text.erb文件),将其中的链接替换为API路由:
<p><%= link_to '重置密码', edit_api_auth_password_url(@resource.reset_password_token, redirect_url: @redirect_url) %></p>
这样所有通过API发起的密码重置请求,邮件都会生成正确的/api/auth/password/edit链接,而Web端发起的重置请求依然使用Devise默认的邮件模板和路由。
测试验证
完成配置后,记得分别测试两种场景:
- 外部Web应用:发送POST请求到
/api/auth/password,检查邮件链接是否指向API路由,且redirect_url参数有效,点击后跳转到外部应用的重置页面。 - Rails Web应用:访问
/users/sign_in确认登录功能正常,发起密码重置后,邮件链接应指向Web端的重置表单。
内容的提问来源于stack exchange,提问作者Baleato
相关产品推荐
相关产品推荐

