9

我正在尝试登录网站并从 rails 操作重定向到安全页面。我的代码看起来像这样。

 def redirect_to_external 
   agent = Mechanize.new
   page = agent.get('http://example.com/home.asp')
   login_form = page.form_with(:name => "loginForm")
   login_form.login = 'username'
   login_form.password = 'password'
   agent.submit(login_form)

   #cookies = agent.cookie_jar.store.map {|i|  i} #need to store the cookie with a specific in browser
   redirect_to('http://example.com/admin.asp') #page behind password protection
 end

在后台登录成功,但实际重定向到管理页面再次要求在浏览器中进行身份验证,因为会话 cookie 未存储在浏览器中。尝试从 存储 cookie cookie_jar,但找不到确切的方法。有人可以帮助我吗?

4

2 回答 2

10

我为这个挣扎了很久!StackOverflow 上的其他答案并没有完全解决如何缓存 cookie 和检索它们,所以我将我的经验与我读过的其他答案结合到一个解决方案中。

(看:

Rails 3 - 登录另一个站点并在会话中保留 cookie

使用 ruby​​ mechanize 在浏览器中存储登录会话 cookie

获取 Mechanize 以处理来自任意 POST 的 cookie(以编程方式登录网站)

保持机械化页面超过请求边界

)。

我使用此解决方案为不支持真正 OAuth2.0 的网站创建自定义 OAuth2.0。

  1. 用户给了我另一个站点的凭据。我在我的 Sessions 控制器的 create 方法中通过 Mechanize 将它们传递到站点并立即销毁它们(我不想尽可能多地触及其他人的安全内容。这就是为什么这一切也发生在 SSL 下)。

  2. 这意味着一旦我在我的应用程序中重定向到其他任何地方,我需要的 cookie 的 Mechanize 实例将被销毁。例如,在我的应用程序中,我接下来重定向到index我的Sessions Controller. 如果您是 Rails 新手,您可能会认为相同的实例变量(例如带有这些 cookie 的机械化代理)可以从createto 获得index,但这是错误的,每个重定向都会破坏一切!(基本上)

  3. 因此,在重定向之前,您需要存储 cookie。在请求之间存储此类内容的唯一方法是通过缓存,并且缓存不喜欢存储整个机械化实例。相反,您需要存储序列化的 cookie。唯一的问题是,Mechanize 没有将其 cookie 输出为字符串的方法,它只能将它们保存为文件。该怎么办?

  4. StringIO 来救援!您基本上可以使用 StringIO 伪造文件。说了这么多,下面是代码:

    @agent = Mechanize.new
    #handle the sign in stuff
    stringio = StringIO.new
    @agent.cookie_jar.save(stringio, session: true)
    cookies = stringio.string
    session[:login_cookies] = cookies
    

请注意,我传递session: true给了cookie_jar. 如果没有该参数,cookie 将只保存非会话 cookie。

  1. 所以现在我们的会话缓存有一个字符串,其中包含来自 mechanize 的所有 cookie。要在重定向后恢复它们,您需要再次使用 StringIO:

    @agent = Mechanize.new
    cookies = session[:login_cookies]
    @agent.cookie_jar.load StringIO.new(cookies)
    
  2. 瞧!您的新代理已准备好像旧代理一样行事。

于 2014-10-21T13:25:17.103 回答
2

请参考以下代码。这将在一个块内创建一个代码,这将保持身份验证,

 def redirect_to_external 
    @agent = Mechanize.new
    @agent.get('http://example.com/home.asp') do | home_page | # Need to pass the others requests into the block
      login_form = home_page.form_with(:name => "loginForm")
      login_form.login = 'username'
      login_form.password = 'password'
      @agent.submit(login_form)
      #cookies = agent.cookie_jar.store.map {|i|  i} #need to store the cookie with a specific in browser
      @agent.get('http://example.com/admin.asp') #page behind password protection
   end  
 end
于 2013-11-29T05:20:19.607 回答