Rails子域名部署:管理员面板固定子域名配置咨询
嘿,这个需求在apartment多租户场景里挺典型的,我来给你捋捋具体的实现方向,一步步来就很清晰:
本质是要区分普通用户和管理员用户的子域名路由逻辑:让管理员的会话固定绑定到app.domain.com,而普通用户保持使用注册时自选的子域名。
1. 先给用户模型添加角色标识
首先得明确谁是管理员,给User模型加个角色字段最直接。比如用enum来定义角色:
# app/models/user.rb class User < ApplicationRecord enum role: [:user, :admin], default: :user # 其他Devise和关联逻辑... end
记得跑迁移把role字段加到users表哦。
2. 自定义登录/验证后的重定向逻辑
Devise允许我们覆盖默认的重定向方法,在application_controller.rb里添加以下代码,区分用户类型跳转:
# app/controllers/application_controller.rb class ApplicationController < ActionController::Base # 其他配置... def after_sign_in_path_for(resource) if resource.admin? # 管理员直接跳固定子域名的后台面板 root_url(subdomain: 'app') else # 普通用户跳自己注册时选的子域名 root_url(subdomain: resource.subdomain) end end def after_confirmation_path_for(resource_name, resource) # 邮箱验证后的重定向逻辑和登录一致 after_sign_in_path_for(resource) end end
3. 配置apartment排除固定子域名
apartment默认会根据子域名自动切换租户,但app.domain.com是全局管理面板,不需要切换到某个用户的租户。打开apartment.rb初始化文件,把这个子域名加入排除列表:
# config/initializers/apartment.rb Apartment.configure do |config| # 其他已有配置... config.excluded_subdomains = ['app', 'www'] # 新增app子域名排除 end
这样访问app.domain.com时,apartment会使用主数据库(存放所有租户和用户信息的库),正好适配管理员查看全局数据的需求。
4. 给管理员路由加子域名约束
为了避免管理员误访问其他子域名的面板,给管理员专属路由加上子域名约束,确保只有app.domain.com能访问:
# config/routes.rb Rails.application.routes.draw do # 管理员专属路由,仅限app子域名访问 constraints subdomain: 'app' do namespace :admin do root 'dashboard#index' resources :users resources :tenants # 如果需要管理租户的话 # 其他管理员功能路由... end end # 普通用户的路由,无特殊约束 root 'home#index' # 其他普通用户路由... end
5. 会话跨子域名配置(可选但重要)
如果管理员需要在不同子域名间切换操作,确保会话能跨子域名共享,修改session_store的配置:
# config/initializers/session_store.rb Rails.application.config.session_store :cookie_store, key: '_your_app_session', domain: '.domain.com'
注意域名前的.,这样所有子域名都能共享会话cookie,但一定要做好权限校验,避免管理员在普通用户子域名下执行敏感操作。
6. 权限加固必不可少
最后,给管理员的控制器加前置校验,确保只有管理员能访问app.domain.com的面板:
# app/controllers/admin/application_controller.rb class Admin::ApplicationController < ApplicationController before_action :authenticate_admin! private def authenticate_admin! unless current_user&.admin? redirect_to root_url(subdomain: current_user&.subdomain || 'www'), alert: '您没有权限访问该页面' end end end
这样一套流程走下来,就能完美实现你要的效果:普通用户验证后跳自选子域名,管理员登录后固定到app.domain.com的管理面板。
内容的提问来源于stack exchange,提问作者Rahul Lakhaney

