Rails应用登录后闲置访问接口出现重定向循环及401错误求助
原因分析
- 401报错核心原因
你在session_store.rb中设置了10年的cookie过期时间,但Devise的config.timeout_in = 25.minutes配置优先级更高,用户登录后闲置满25分钟,Devise会主动销毁会话有效性,此时current_user就会返回空,触发401响应,和你配置的cookie过期时间无关。 - 重定向循环原因
Devise默认对未登录的请求会触发302重定向到登录页,如果你未覆盖Devise的默认未登录处理逻辑,会话过期时请求会先被Devise拦截返回302;加上Postman默认开启自动跟随重定向,如果登录页逻辑又跳转回原请求地址,就会触发无限循环,导致Postman报错。
排查步骤
- 确认ApiController及子类是否引入了Devise的
authenticate_user!前置回调:如果加了这个回调,它的执行优先级高于你自定义的check_user,会话过期时Devise会直接触发302重定向,不会走到你写的返回401的逻辑 - 查看Postman的重定向设置:是否开启了「Automatically follow redirects」,开启后遇到302响应会自动跳转,触发循环时就会报对应错误
- 验证Devise timeout规则:登录后分别在25分钟以内、25分钟以上请求接口,看返回结果是否符合25分钟过期的规律,确认是
timeout_in配置生效导致的会话过期 - 检查自定义
check_user的执行情况:在check_user方法里加日志,看会话过期时该方法是否被执行,有没有被Devise的默认回调拦截
解决方案
1. 解决会话过期问题(按需二选一)
- 如果你确实需要长期会话适配移动端需求,直接把Devise的
config.timeout_in设置为和session_store匹配的时长即可,比如config.timeout_in = 10.years,覆盖默认的25分钟过期规则 - 如果需要保留闲置超时逻辑,就在客户端加401响应的捕获逻辑,遇到401时自动跳转到登录页重新登录
2. 解决重定向循环问题
禁用Devise对API请求的默认重定向行为,给API控制器添加如下配置即可:
class ApiController < ActionController::Base # 告诉Devise这是JSON请求,不要重定向,直接返回401 protect_from_forgery with: :null_session before_action :configure_devise_params, if: :devise_controller? # 覆盖Devise的默认未登录处理逻辑 def authenticate_user! if request.format.json? current_user.present? ? super : render(json: { err: 'Faça seu login antes de continuar' }, status: 401) else super end end # 原有逻辑保持不变 before_action :check_user, except: %i[signin signinEmployee signup signupEmployee forgotPass getFaq getMessages updatePassword contactus getBanners getPartners getCategories getServices getAllServices getServiceDetails getRecommended checkCode getInstructions checkCpf emailCode checkEmail getPipefyUrl log] skip_before_action :verify_authenticity_token def check_user return if current_user.present? render json: { err: 'Faça seu login antes de continuar' }, status: 401 end private def configure_devise_params # 你需要的Devise参数白名单可以在这里添加 devise_parameter_sanitizer.permit(:sign_up, keys: [:name, :phone, :cpf]) end end
3. Postman测试适配
在Postman的设置里关闭「Automatically follow redirects」,测试时就能直接看到接口真实的响应状态码和内容,不会触发循环跳转的报错。
内容的提问来源于stack exchange,提问作者Gustavo Trivelatto
相关产品推荐
相关产品推荐

