Devise 非预期持续重定向至new_user_session_path问题排查
问题排查:Rails+Devise测试中登录用户仍被重定向至登录页
问题详情
在测试Rails应用的ContactsController时遇到异常:
- 未添加
before_action :authenticate_user!时,已通过sign_in登录的用户访问new动作仍被重定向至http://www.example.com/users/sign_in - 添加该前置动作后,所有测试均触发此重定向
测试环境:Ruby 3.1.2、Rails 7.0.4、Devise 4.8.1,代码中无手动重定向至new_user_session_path的语句
相关代码
ContactsController代码
class ContactsController < ApplicationController before_action :set_contact, only: %i[ show edit update destroy ] def new @contact = Contact.new end end
测试代码
require "test_helper" class ContactsControllerTest < ActionDispatch::IntegrationTest include Devise::Test::IntegrationHelpers setup do @contact = contacts(:one) @admin = users(:admin) @one = users(:one) @two = users(:two) end test "blank slate" do get new_contact_url assert_response :success end # => 1 assertions test "should get new" do sign_in @admin get new_contact_url assert_response :success end # => was a <302: Found> redirect to <http://www.example.com/users/sign_in> test "fail test just to see what happens" do sign_in @one get new_contact_url assert_redirected_to root_path end # => Expected response to be a redirect to <http://www.example.com/> but was a redirect to <http://www.example.com/users/sign_in>.
添加before_action :authenticate_user!后,第一个测试返回:
Expected response to be a <2XX: success>, but was a <302: Found> redirect to http://www.example.com/users/sign_in
其余两个测试结果与之前一致。
ApplicationController代码
before_action :configure_permitted_parameters, if: :devise_controller? protected def configure_permitted_parameters attributes = [:email, :password, :password_confirmation, :name_last, :name_first, :public_persona] devise_parameter_sanitizer.permit(:sign_up, keys: attributes) devise_parameter_sanitizer.permit(:account_update, keys: attributes) end
排查方向
- 检查测试用户的激活状态:Devise默认会拦截未激活用户的登录请求,即使调用
sign_in也无法建立有效会话。需确认测试fixtures中的用户(如users(:admin))是否设置了confirmed_at字段,或在测试的setup方法中添加@admin.confirm!完成激活。 - 验证登录状态是否生效:在测试中添加
assert user_signed_in?断言,确认sign_in方法确实成功创建了用户会话,排除测试助手调用异常的可能。 - 排查全局认证逻辑:检查
ApplicationController或继承的父类/concern中是否存在隐藏的before_action :authenticate_user!,导致所有控制器动作都被强制要求认证。 - 检查测试环境会话配置:查看
config/environments/test.rb中的会话设置,确认config.session_store正常启用,无特殊cookie配置导致会话无法持久化。 - 验证路由匹配:确认
new_contact_url对应的路由没有子域名、命名空间等约束,避免请求未匹配到预期的ContactsController#new动作,触发其他认证拦截逻辑。
内容的提问来源于stack exchange,提问作者Jerome
相关产品推荐
相关产品推荐

