Rails 6非生产环境ActionMailer预览HTTP基础认证配置缺失咨询
我在production.rb里有如下ActionMailer配置:
unless ENV['APP_NAME'] == 'application-production' config.action_mailer.preview_path = Rails.root.join('test/mailers/previews') config.action_mailer.show_previews = true end
现在遇到的问题是:staging这类非生产环境里,整个域名(包括邮件预览路径/rails/mailers)都应该启用HTTP基础认证,但目前这个邮件预览路径不需要认证就能直接访问。我尝试添加了初始化器,想在里面用ActionController::Base.http_basic_authenticate_with,但发现这个方法不可用,想知道缺少什么配置或者正确的实现方式是什么?
其实你碰到的核心问题是:Rails的邮件预览控制器(Rails::MailersController)并没有继承自你的项目里的ApplicationController,所以直接在ActionController::Base上配置认证,或者用你之前的方式操作,都不会作用到邮件预览页面上。这里给你几个实用的解决办法:
方案1:通过路由约束添加认证(推荐)
直接在config/routes.rb里给邮件预览的路由加上HTTP基础认证约束,逻辑清晰且不会影响其他控制器:
Rails.application.routes.draw do # 你的其他路由配置... # 只在非生产环境启用带认证的邮件预览 if ENV['APP_NAME'] != 'application-production' constraints ->(request) { authenticate_or_request_with_http_basic('Protected Staging Environment') do |username, password| # 建议用环境变量存储账号密码,避免硬编码 username == ENV['STAGING_AUTH_USER'] && password == ENV['STAGING_AUTH_PASS'] end } do mount Rails::MailersController => '/rails/mailers' end end end
这样只要访问/rails/mailers路径,就会弹出HTTP基础认证窗口,只有输入正确的账号密码才能访问。
方案2:给邮件预览控制器动态添加认证过滤器
创建一个初始化器(比如config/initializers/mailer_preview_authentication.rb),直接给Rails::MailersController添加前置认证逻辑:
if ENV['APP_NAME'] != 'application-production' Rails::MailersController.class_eval do before_action :require_http_authentication private def require_http_authentication authenticate_or_request_with_http_basic('Mailer Preview Access') do |username, password| username == ENV['STAGING_AUTH_USER'] && password == ENV['STAGING_AUTH_PASS'] end end end end
之前你用ActionController::Base.http_basic_authenticate_with没用,是因为这个方法是给控制器类配置全局认证的,但邮件预览控制器没继承你的基类,所以直接给它动态注入过滤器才是正确的姿势。
方案3:让邮件预览控制器继承你的ApplicationController(不推荐)
如果你的ApplicationController已经全局配置了HTTP基础认证,可以让邮件预览控制器继承它,但这个方法有点hack,可能带来不必要的副作用:
# config/initializers/override_mailer_preview_parent.rb if ENV['APP_NAME'] != 'application-production' Rails::MailersController.class_eval do inherit ApplicationController end end
这样它会自动继承ApplicationController里的所有认证逻辑,但要注意如果你的ApplicationController有其他前置过滤器,也会被应用到邮件预览页面上,可能导致异常。
内容的提问来源于stack exchange,提问作者user63764

