You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用ruby-saml实现OmniAuth时request.env['omniauth.auth']为空如何解决

问题核心原因

你当前的SAML认证流程完全基于ruby-saml手动实现,没有走OmniAuth的标准处理流程,因此OmniAuth中间件不会自动解析SAML响应、生成omniauth.auth和omniauth.params数据,这就是你取值为nil的根本原因。Google OAuth2流程走了OmniAuth注册的provider,所以可以正常获取数据。

你需要动态配置SAML的idp_sso_target_url和idp_cert的需求,完全可以通过OmniAuth SAML的动态配置能力实现,无需自己手动实现整套SAML逻辑。


具体解决步骤

1. 新增依赖

在Gemfile中添加omniauth-saml依赖,执行bundle install:

gem 'omniauth-saml'

2. 修改OmniAuth初始化配置

在OmniAuth初始化文件中注册SAML provider,通过setup参数实现动态配置:

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :google_oauth2,
       CONFIG[:google_client_id],
       CONFIG[:google_client_secret],
       access_type: 'online'

  # 新增SAML provider配置
  provider :saml,
    # 动态配置回调,可从请求、数据库、配置文件读取动态参数
    setup: ->(env) {
      request = Rack::Request.new(env)
      opts = env['omniauth.strategy'].options
      # 动态IDP配置,你后续需要改参数直接修改这里的取值逻辑即可
      opts[:idp_sso_target_url] = CONFIG[:saml_sso_target]
      opts[:idp_cert] = CONFIG[:saml_cleint_certificate]
      # 固定配置
      opts[:assertion_consumer_service_url] = "#{request.base_url}/auth/saml/callback"
      opts[:issuer] = '1234567890'
      opts[:name_identifier_format] = 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'
      opts[:idp_cert_fingerprint_algorithm] = 'http://www.w3.org/2000/09/xmldsig#sha256'
    },
    callback_path: '/auth/saml/callback'

  on_failure { |env| Authentication::OmniauthController.action(:failure).call(env) }
end

# 允许POST请求发起SAML认证,适配你的表单提交逻辑
OmniAuth.config.allowed_request_methods = [:get, :post]
OmniAuth.config.logger = Rails.logger

3. 调整路由

删除你之前自定义的SAML相关路由,新增SAML回调路由:

# 删除以下两行自定义路由
# post 'auth/saml', to: 'authentication/saml#saml', as: :saml_authorize
# post 'auth/saml/callback', to: 'authentication/saml#callback'

# 新增SAML回调路由,和Google OAuth2的回调逻辑统一处理
get '/auth/saml/callback' => 'authentication/omniauth#saml'
get '/auth/google_oauth2/callback' => 'authentication/omniauth#google_oauth2'
get 'omniauth/failure' => 'authentication/omniauth#failure'

4. 调整视图表单

将表单提交地址改为OmniAuth标准的SAML发起路径:

<%= form_tag '/auth/saml', class: 'text-center' do %>
    <%= select_tag :user_type, options_for_select([[t('.option_user'), 'user'], [t('.option_serviceuser'), 'service_user']], sel_obj_class_name), class: 'js-select-user-type platform-select-service' %>
    <button class="btn btn-light">
        SAML Auth
    </button>
<% end %>

5. 新增SAML回调处理逻辑

在Authentication::OmniauthController中新增SAML回调方法,直接从env中取OmniAuth生成的标准数据即可:

def saml
  # 这里可以正常拿到你表单提交的user_type参数
  user_type = request.env['omniauth.params']['user_type']
  # 标准OmniAuth认证信息
  auth_hash = request.env['omniauth.auth']

  user = if user_type == 'service_user'
           User.from_omniauth(auth_hash)
         else
           User.from_omniauth(auth_hash)
         end

  if user
    flash[:notice] = I18n.t 'devise.omniauth_callbacks.success', kind: 'Saml'
    sign_in_and_redirect user, event: :authentication
  else
    redirect_to signin_path, alert: t('devise.failure.invalid')
  end
end

你之前手动实现的SamlController可以直接废弃,OmniAuth SAML已经封装了SAML请求生成、响应校验、数据解析的全部逻辑,还能兼容你动态配置IDP参数的需求。

内容的提问来源于stack exchange,提问作者Umes Bastola

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 08:18:02