【问题标题】:Passing parameters through OmniAuth通过 OmniAuth 传递参数
【发布时间】:2012-03-27 13:54:41
【问题描述】:

我需要将一些参数传递给回调操作。从源代码来看,OmniAuth 应该在回调 URL 中添加查询字符串,但奇怪的是它没有。当我打开

/auth/facebook?from=partner

...然后被重定向到 Facebook,return_url 只是

/auth/facebook/callback

...没有任何参数。

【问题讨论】:

标签: ruby-on-rails omniauth


【解决方案1】:

在解决了上述所有问题后,我想出了如何处理Facebook,默认情况下它不会显示request.env["omniauth.auth"] 中的参数。

所以 -- 如果您使用查询字符串进行回调,类似于这样:

"/auth/facebook?website_id=#{@website.id}"

获取该 website_id 参数的唯一方法是使用request.env["omniauth.params"]。 注意:请确保您使用omniauth.params 而不是omniauth.auth——这个让我有一阵子绊倒了。

然后,要对此进行测试,您可以在控制器操作中对其进行检查(注意 RAISE 行...):

def create
  raise request.env["omniauth.params"].to_yaml 
  # the rest of your create action code...
end

你应该在那里看到你的参数。伟大的。现在,回到您的控制器并删除该 RAISE 线。然后,您可以在控制器操作中按如下方式访问参数:

params = request.env["omniauth.params"]
website_id = params["website_id"]

注意:在 params["website_id"] 中,您需要使用引号而不是符号。

【讨论】:

  • 我在 omniauth.auth 中得到了输出,但在 omniauth.params 中得到了输出。怎么了?我已经在 URL 中传递参数。 "/auth/facebook/state=123"
  • @harsh4u 可能是因为您的网址缺少“?”在参数之前。它应该是“auth/facebook/?state=123”
  • 谢谢你!在阅读您的答案之前,我正在劫持 state 参数以实现此目的。谢谢!
  • 这是omniauth的一个很棒的功能,可惜没有更好的文档记录。
【解决方案2】:

我猜 cookie 是可行的,但是当您可以使用此处记录的状态变量时,为什么还要这样做:https://github.com/mkdynamic/omniauth-facebook

我是这样用的:

在创建 url 时,您只需在查询字符串中添加状态,它也将在回调 url 中可用。

user_omniauth_authorize_path(:facebook, :display => 'page', :state=>'123') %>

现在回调 url 将是

http://localhost:3000/users/auth/facebook/callback?state=123&code=ReallyLongCode#_=_

现在您可以在回调处理程序中处理状态

【讨论】:

    【解决方案3】:

    您可以使用:params 选项,如

    omniauth_authorize_path(:user, :facebook, var: 'value', var2: 'value2' )
    

    稍后在回调中,您可以访问request.env['omniauth.params'] 以获取哈希! :)

    (复制自this answer)

    【讨论】:

    • 一个救命稻草,在最底层持续很长时间:)
    • 你拯救了我的一天。谢谢!
    【解决方案4】:

    您要做的是根据每个身份验证事务动态设置回调以在 url 中包含合作伙伴名称(不是 url参数),具体取决于涉及哪个合作伙伴。这意味着为每个身份验证请求动态设置回调 url。见this blog post to get started。正如您所注意到的,回调 url 会自动删除 url 参数,因此使用参数执行此操作将不起作用。

    因此,如果您没有尝试将合作伙伴名称/ID 作为参数(已删除)传递,而是构建了您的路由,以便 partner_id 和 OmniAuth provider 成为回调 url 的一部分,那么您会有类似的东西:

    /auth/:omniauth_provider/callback/:partner_id
    

    ...有效的回调类似于

    /auth/facebook/callback/123456
    

    ...那么您就会知道给定的回调来自 facebook,合作伙伴 ID 为 123456

    【讨论】:

    • 很好的答案,Normalocity。我试图自己弄清楚这一点。我不太确定如何执行您上面规定的操作,并且博客文章也没有说明太多。你能发布一些代码吗?具体来说,如何生成上述路由以及如何创建相应的控制器操作来处理不同的回调?我特别希望回调提供用户离开的上下文,这样我可以在 OAuth 完成后将用户返回到他们所在的位置。
    • 当用户被重定向到oauth门户时,用户“离开”的url可以存储在cookie中,当回调返回时,可以查找cookie,检索值,并且 cookie 已过期/已删除。至于其他的东西,我认为我最好推出一个快速演示应用程序并将其作为概念验证发布,然后我可以在 github 上分享代码。然后,假设它有效,我可以在答案中将代码发回此处。给我几个小时来试一试。
    【解决方案5】:

    OmniAuth 已经有一个内置的方法来知道用户在哪里,它被称为“原点”,如此处所述:

    https://github.com/intridea/omniauth/wiki/Saving-User-Location

    【讨论】:

      【解决方案6】:

      你知道,我想我可能正在努力解决这个问题。

      Cookie 可能就是答案。我认为您可以通过让您的登录操作存储一个 cookie 来解决这个问题,然后重定向到正确的 /auth/:provider 路径进行身份验证,当触发回调时(在 SessionsController#create 中),您只需读取 cookie 即可知道在哪里将它们重定向到。

      所以,现在,您的“使用 facebook 登录”链接(或您的应用程序中的任何内容)可能会转到 /auth/facebook。相反,如果您创建了像

      这样的自定义操作
      POST /partner_auth
      

      ...并用 url 调用它...

      POST example.com/partner_auth?from=partner&provider=facebook
      

      那么你可能有一个控制器:

      class PartnerAuth < ApplicationController
        def create
          cookies[:from] = params[:from]  # creates a cookie storing the "from" value
          redirect_to "auth/#{params[:provider]"
        end
      end
      

      然后在SessionsController#create 操作中,您将...

      def create
        ...
      
        destination = cookies[:from]
        cookies[:from].delete
      
        redirect_to destination    # or whatever the appropriate thing is for your
                                   # app to do with the "from" information
      end
      

      我尝试构建一个演示应用程序来完成我在另一个答案中概述的内容,但您是对的 - 尝试将自定义回调动态注入 OmniAuth 代码太复杂了。有一个配置选项可以覆盖默认回调,但动态设置似乎并不容易。

      所以,我突然意识到 cookie 会更简单,特定于用户,因为理论上您只需要在很短的时间内存储此 from 信息(在用户尝试进行身份验证和回调被触发),创建一个cookie并在回调被命中时删除它没有什么大不了的。

      【讨论】:

        【解决方案7】:

        使用“状态”变量。 Facebook 允许用户设置状态变量。

        我是这样做的,我在 AUTH URL 中附加了 ?state=providername

        http://localhost/users/auth/facebook?state=providername
        

        这个参数在回调中作为参数['providername']返回给我

        我从最初的 Omniauth 路径方法设计解决方案

        user_omniauth_authorize_path(:facebook, :display => 'page', :state=>'123') %>
        

        【讨论】:

        • 这是非常糟糕的方法。状态参数用于避免来自另一个域的令牌伪造。状态是一个生成的密钥,它与用户一起传递给 IDP 并由 IDP 返回,因此您可以仔细检查此身份验证请求是否真的由您的服务器发出。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-25
        • 2014-05-22
        • 1970-01-01
        • 2023-04-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多