Rails 7 部署至render.com后生产环境登录异常求助
Rails 7部署到render.com后登录持续重定向问题
问题现象
本地开发模式下登录验证功能正常,部署到render.com后,登录成功后会持续重定向回登录页面。怀疑问题与TURBO_STREAM或生产环境会话处理机制有关。
相关日志
I, [xxx] INFO -- : [xxc681] Parameters: {"authenticity_token"=>"[FILTERED]", "session"=>{"email"=>"admin@admin.com", "password"=>"[FILTERED]"}, "commit"=>"Log in"} I, [xxx] INFO -- : [xxc681] Redirected to https://myapp.onrender.com/dashboard I, [xxx] INFO -- : [xxc681] Completed 302 Found in 2241ms (ActiveRecord: 78.1ms | Allocations: 29973) I, [xxx] INFO -- : [xx4e31] Started GET "/dashboard" for 172.71.98.11 at 2024-02-24 20:46:23 +0000 I, [xxx] INFO -- : [xx4e31] Processing by AgreementsController#index as TURBO_STREAM I, [xxx] INFO -- : [xx4e31] Redirected to https://myapp.onrender.com/login
控制器代码
AgreementsController
class AgreementsController < ApplicationController include Auditable before_action :logged_in_user before_action :check_subscription before_action :check_credit, only: [:show] def index @user = current_user @q = Agreement.ransack(params[:q]) end end
ApplicationController
class ApplicationController < ActionController::Base protect_from_forgery with: :exception include SessionsHelper # callbacks before_action :set_auditlog_variables # Make active_user variable available in the Auditable concern def set_auditlog_variables AuditLog.active_user = current_user if logged_in? end private # Confirms a logged-in user. def logged_in_user unless logged_in? store_location flash[:danger] = "Please log in." redirect_to login_url, status: :see_other end end end
会话助手方法
module SessionsHelper # Logs in the given user. def log_in(user) session[:user_id] = user.id session[:session_token] = user.session_token user.create_session_log(:login) end def current_user if (user_id = session[:user_id]) user = User.find_by(id: user_id) if user && session[:session_token] == user.session_token @current_user = user end elsif (user_id = cookies.encrypted[:user_id]) user = User.find_by(id: user_id) if user && user.authenticated?(:remember, cookies[:remember_token]) log_in user @current_user = user end end end # Returns true if the given user is the current user. def current_user?(user) user && user == current_user end # Returns true if the user is logged in, false otherwise. def logged_in? !current_user.nil? end end
解决建议
1. 修复Turbo Stream重定向处理
从日志可见,/dashboard请求是以TURBO_STREAM格式处理的,Turbo对重定向的逻辑和普通HTTP请求不同,可能导致会话状态未正确同步。修改登录校验回调中的重定向逻辑,强制返回HTML格式:
def logged_in_user unless logged_in? store_location flash[:danger] = "Please log in." redirect_to login_url, status: :see_other, format: :html end end
同时在登录成功后的重定向中也明确指定格式:
# 登录控制器的create方法示例 def create # ... 登录逻辑 ... redirect_to dashboard_url, format: :html end
2. 检查生产环境会话配置
在config/environments/production.rb中确认会话存储的安全配置,适配Render的HTTPS环境:
Rails.application.configure do # 开启cookie安全属性,HTTPS环境必须配置 config.session_store :cookie_store, key: '_your_app_session', secure: true, same_site: :lax # 若使用自定义域名,需指定domain属性 # config.session_store :cookie_store, key: '_your_app_session', domain: '.yourdomain.com' end
另外确保Render的环境变量中已正确设置SECRET_KEY_BASE,生产环境依赖该值加密会话数据。
3. 修复会话令牌校验逻辑
当前log_in方法直接使用用户现有session_token,可能导致令牌重复或未持久化到数据库。修改User模型的令牌生成逻辑:
class User < ApplicationRecord def session_token @session_token ||= generate_session_token end def reset_session_token! self.session_token = generate_session_token save! session_token end private def generate_session_token SecureRandom.urlsafe_base64 end end
然后更新log_in方法,确保每次登录生成新令牌:
def log_in(user) user.reset_session_token! session[:user_id] = user.id session[:session_token] = user.session_token user.create_session_log(:login) end
4. 确认Turbo会话共享设置
Turbo默认会携带会话cookie,但需确保域名与cookie配置一致。检查same_site属性设置为:lax或:strict,避免跨域会话丢失问题。
内容的提问来源于stack exchange,提问作者Matthias
相关产品推荐
相关产品推荐

