2

我们有一个由另一个开发人员构建的新 Web 应用程序。我的工作是为其他程序实现一个后端 API,用于与数据库交换 XML 数据。它进展顺利,直到主应用程序实现了对用户进行身份验证的设计。我想我可以调整 curl 命令以登录然后提交/请求数据,但进展并不顺利。我正在尝试类似的事情

curl --cookie-jar ~/Desktop/cjar --data "user[login]=<username>" --data "user[password]=<pwd>" --data "commit=Sign in" localhost:3000/users/sign_in

其次是

curl --cookie ~/Desktop/cjar --data "<root_node></root_node>" localhost:3000/my_update_method

我最新的错误信息是

WARNING: Can't verify CSRF token authenticity
Completed 401 Unauthorized in 1ms

我想这比我收到的重定向消息要好,但我仍然不知道发生了什么。

我发现一些相关的帖子让我认为这部分与设计有关,部分与 Rails 完成的自动身份验证有关。当我查看网页传递的信息时,我看到了我不知道如何为 curl 命令构建的authenticity_token 和utf8 参数。

我可以继续尝试,但我对 curl 和身份验证都是新手,所以我有点在黑暗中拍摄,希望有人能帮我节省一些时间。我想我的问题是:

  1. 这可以做到吗?
  2. 应该这样做吗?如果没有,我还有什么其他选择?
  3. 一篇文章提出了一种绕过身份验证的方法,但是否可能只有 curl 命令需要登录/密码,但绕过任何其他验证,而不影响主 Web 应用程序?

更新 1:

感谢所有的帮助,我很感激。对第一个 curl 命令(如上所列)的响应现在只是重定向到登录页面,因此似乎不需要登录。有人对从哪里开始调试有任何建议吗?没有任何东西进入应用程序,因此没有日志可供查看。这是 cookie 的内容,如果它对任何人都有意义的话:

# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This file was generated by libcurl! Edit at your own risk.

#HttpOnly_localhost FALSE   /   FALSE   0   _glow_session   BAh7B0kiCmZsYXNoBjoGRUZvOiVBY3Rpb25EaXNwxhc2g6OkZsYXNoSGFzaAk6CkB1c2VkbzoIU2V0BjoKQGhhc2h7ADoMQGNsb3NlZEY6DUBmbGFzaGVzewY6C25vdGljZUkiHFNpZ25lZCBpbiBzdWNjZXNzZnVsbHkuBjsAVDoJQG5vdzBJIg9zZXNzaW9uX2lkBjsARkkiJTIwODc1Y2VjM2ViNzlmZDE3ZjA4ZjVmMDAxNWMxMDU4BjsAVA%3D%3D--d90722b6da386630b33f57902447b440f30d0b2a

我已经添加skip_before_filter :verify_authenticity_token到处理 api 请求的控制器中,这消除了我之前看到的错误。

更新 2:

经过一些故障排除和调试后,我想我可能实际上可以正常登录,但是当我执行第二次 curl 时,development.log 文件显示

Started POST "/upsert_experiment" for 127.0.0.1 at 2013-10-16 12:14:12 -0500
Processing by WebServiceController#upsert_experiment as */*
  Parameters: {"experiment_xml"=>"<experiment></experiment>"}
Completed 401 Unauthorized in 1ms

这让我认为授权仍然是问题。

更新 3:

我认为问题在于它skip_before_filter :verify_authenticity_token不起作用。

我有

class ApplicationController < ActionController::Base
  rescue_from DeviseLdapAuthenticatable::LdapException do |exception|
    render :text => exception, :status => 500
  end
  protect_from_forgery
  before_filter :authenticate_user!
end

class WebServiceController < ApplicationController
  skip_before_filter :verify_authenticity_token
  ...
end

使用此设置,我得到“在 1 毫秒内完成 401 未授权”。如果我在超类中注释掉protect_from_forgery 行,它就可以工作,所以伪造保护肯定是问题所在。我只是不知道如何解决它。

4

3 回答 3

2

您缺少 CSRF 令牌。这是为了防止跨站点请求伪造。

于 2013-10-15T20:34:06.027 回答
2

CSRF 代表 Cross Site Request Forgery,是一种安全保护,您可以在此处了解更多信息。本质上,rails 会生成一个包含在页面上呈现的表单中的随机令牌,并且它希望在表单提交时获得该令牌。您不需要对 api 进行这种保护,但它对 web 应用程序端很重要。有关禁用 CSRF 令牌的方法,请参阅此问题。

您可能采取的一种方法是使用token_authenticableDevise 模块并使用 验证您的请求auth_token=#{token},然后如果存在身份验证令牌则跳过 CSRF 保护。

于 2013-10-15T20:35:09.080 回答
2

Rails CSRF 保护阻止您提出此请求。

来自 Rails 文档

CSRF protection automatically include a security token, calculated from the current session and the server-side secret, in all forms and Ajax requests generated by Rails. You won't need the secret, if you use CookieStorage as session storage. If the security token doesn't match what was expected, the session will be reset. Note: In Rails versions prior to 3.0.4, this raised an ActionController::InvalidAuthenticityToken error.

如果您想跳过它,请将此行添加到您的控制器

skip_before_action :verify_authenticity_token, :only => ["your_update_action"]
于 2013-10-15T20:36:36.323 回答