Ruby on Rails OAuth应用程序可在客户端上运行,但不在服务器上运行(OAuth :: Unauthorized(401 Unauthorized))

时间:2010-10-06 02:00:22

标签: ruby-on-rails authentication oauth twitter-oauth

我有一个Ruby on Rails应用程序,它在我的计算机和服务器中运行良好。我正在将此应用程序移动到另一台运行在另一台托管服务上的服务器,我遇到了与OAuth Ruby Gem相关的问题。

我使用OAuth gem做的任何请求,我得到:

OAuth::Unauthorized (401 Unauthorized):
  oauth (0.4.3) lib/oauth/consumer.rb:217:in `token_request'
  oauth (0.4.3) lib/oauth/consumer.rb:139:in `get_request_token'
  ...

我的代码是:

def self.consumer
  # The readkey and readsecret below are the values you get during registration
  OAuth::Consumer.new("XXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "YYYYYYYYYYYYYYYYYYYYYYYYYYYY", {:site => "http://api.twitter.com"})
end

def create_authorize_url
  @request_token = UserController.consumer.get_request_token(:oauth_callback => "http://mysite.com/callback")
  session[:request_token] = @request_token.token
  session[:request_token_secret] = @request_token.secret

  redirect_to @request_token.authorize_url
end

问题是相同的代码在我的计算机和其他服务器上运行良好。这只发生在一台服务器上。有什么与防火墙有关或可以阻止OAuth呼叫的东西吗?

我经常搜索这个错误而且没有得到任何答案,这就是我在这里问这个问题的原因。

感谢。

6 个答案:

答案 0 :(得分:1)

我发现我的Twitter Consumer Key和Secret在config / application.yml中,并且这个文件在.gitignore中列出,因为它没有被推送到Heroku。结果,这个401错误出现在Twitter OAuth上,因为该应用程序的凭据丢失了。解决方案是在.gitignore文件中找到包含您的Twitter(或其他OAuth提供商)应用程序凭据的任何配置文件的行。从.gitignore中删除该行后,执行

git add .
git commit -m "Added back configuration files for OAuth provider"

如果你在heroku上,那么你可以做

git push heroku master

希望这应该有用。

答案 1 :(得分:0)

对不起。服务器上安装的gem:

root@server1:~# gem list

*** LOCAL GEMS ***

actionmailer (2.3.8)
actionpack (2.3.8)
activerecord (2.3.8)
activeresource (2.3.8)
activesupport (3.0.0, 2.3.8)
addressable (2.2.1)
builder (2.1.2)
facebook_oauth (0.2.0)
faraday (0.4.6)
ffi (0.6.3)
hpricot (0.8.2)
json (1.2.4)
mime-types (1.16)
multi_json (0.0.4)
oauth (0.4.3, 0.3.5)
oauth2 (0.0.13)
rack (1.1.0)
rails (2.3.8)
rake (0.8.7)
ruby-hmac (0.4.0)
ruby-mysql (2.9.3)
rubygems-update (1.3.7)
sqlite3-ruby (1.3.1)
tmail (1.2.7.1)
twitter_oauth (0.4.3)

服务器的Ruby版本:

root@server1:~# ruby -v
ruby 1.8.7 (2010-01-10 patchlevel 249) [x86_64-linux]

感谢您的帮助。

答案 2 :(得分:0)

好的,这是工作服务器gems和Ruby版本。

宝石:

root@phcf:/www/rails# gem list

*** LOCAL GEMS ***

aaronp-frex (1.0.1)
actionmailer (2.3.8, 2.3.5)
actionpack (2.3.8, 2.3.5)
activerecord (2.3.8, 2.3.5)
activeresource (2.3.8, 2.3.5)
activesupport (2.3.8, 2.3.5)
addressable (2.2.1)
chronic (0.2.3)
configuration (1.1.0)
daemons (1.0.10)
eventmachine (0.12.10)
facebook_oauth (0.2.0)
faraday (0.4.6)
fastthread (1.0.7)
gemcutter (0.5.0)
gruff (0.3.6)
heroku (1.10.8, 1.9.13)
highline (1.5.2)
hoe (2.5.0)
hpricot (0.8.2)
json (1.2.2)
json_pure (1.2.3)
launchy (0.3.7)
mime-types (1.16)
multi_json (0.0.4)
mysql (2.8.1)
net-sftp (2.0.4)
net-ssh (2.0.23)
nokogiri (1.4.1)
oauth (0.4.3)
oauth2 (0.0.13)
passenger (2.2.9)
pastiepacker (1.1.1)
rack (1.1.0, 1.0.1)
rails (2.3.8, 2.3.5)
rake (0.8.7)
rest-client (1.4.2)
rmagick (2.12.2)
rubyforge (2.0.4)
rubygems-update (1.3.5)
shared-mime-info (0.1)
steam-condenser (0.10.0, 0.9.0)
thin (1.2.5)
tmail (1.2.7.1)
twitter_oauth (0.4.3)
unicorn (0.96.1)
xmpp4r (0.5)
xmpp4r-simple (0.8.8)

Ruby版本:

root@phcf:/www/rails# ruby -v
ruby 1.8.7 (2008-08-11 patchlevel 72) [x86_64-linux]

答案 3 :(得分:0)

尝试抢救OAuth::Unauthorized异常并检查其包装的响应。类似的东西:

def create_authorize_url
  @request_token = UserController.consumer.get_request_token(:oauth_callback => "http://mysite.com/callback")
  session[:request_token] = @request_token.token
  session[:request_token_secret] = @request_token.secret

  redirect_to @request_token.authorize_url
rescue OAuth::Unauthorized => e
  logger.error e.response.inspect
end

OAuth提供商可能会在他们发送给您的401回复中添加其他信息。请求令牌请求上的401对我来说似乎有些奇怪,但oauth spec does talk about it some

我怀疑的是,由于行为不当,您要使用的托管服务可能会被提供商阻止。在这种情况下,你需要与他们谈谈它。

但是,如果没有更多信息,我们真的不知道为什么。

答案 4 :(得分:0)

我的猜测是时间偏差了。尝试使用ntpdate同步时钟(并且通常使用ntp也是一个好主意)。

答案 5 :(得分:0)

您尝试使用的服务器环境很可能正在使用某种反向代理设置,其中OAuth服务器具有内部地址和端口,而您的OAuth客户端只能看到外部可路由地址。

这会在客户端和服务器上产生不同的签名基本字符串,因此在验证期间会给您一个授权错误!

我们的设置中存在类似的问题,其中一切都在开发环境中正常运行,但在生产中我们的网络设置非常不同(DMZ等)。

当我们使用Nginx时,解决方案是使用proxy_set_header指令将外部主机传递到内部应用程序服务器:

  server {
     # The external IP
     listen x.x.x.x; 
     ...
     location /api {
        # Internal app server
        proxy_pass http://192.168.1.100:4000;

        # Pass the external IP to the app server
        proxy_set_header Host $host; 
     }
     ....
  }

但是还要先检查你的服务器时钟,NTP是你的朋友。