跨应用/服务器的Rails身份validation

我一直在开发我的rails应用程序,同时尽可能保持模块化。 我正在尝试将下面的不同部分实现为服务。

举个Facebook的例子:
a)允许用户拥有墙壁,post等的MainApp
b)存储照片的PhotoApp ,允许用户查看他的照片等。这是一个独立的应用程序,它将具有可由MainApp使用的REST API。

我正在考虑将OAuth用作单点登录解决方案(如本教程中所述http://blog.joshsoftware.com/2010/12/16/multiple-applications-with-devise-omniauth-and-single-sign-on / )其中每个应用程序将通过OAuth授权,并将基于cookie访问当前用户会话。

第一个问题:这是可行的解决方案吗?

第二个问题:我希望能够从MainApp服务器(而不是用户的浏览器)调用PhotoApp API。 如何在这种情况下进行身份validation?

第三个问题:如果说我有一个使用node.js的服务,它将如何工作?

是的,使用OAuth的SSO是一个可行的解决方案,但它并不是最简单的解决方案。 构建任何新东西时, OAuth 2.0都是可行的方法。 OAuth标准涵盖了很多方面。

OAuth的主要优势在于,它允许用户在不向第三方透露密码的情况下授予第三方应用访问其帐户的权限 。 如果您没有认真提供这样的互操作性,那么OAuth可能就是过度杀伤力。

鉴于复杂性,我提供了一对不同的解决方案:

单点登录

诀窍是在域中的主机之间共享会话ID cookie并使用共享会话存储(如ActiveRecordStore或基于缓存的存储)。

每个Rails应用程序都有一个用于签名cookie的“秘密”。 在较新的Rails应用程序中,它位于/config/initializers/secret_token.rb 。 在每个应用程序中设置相同的秘密令牌。

然后,配置会话以允许从所有子域进行访问:

 AppName::Application.config.session_store :active_record_store, :key => '_app_name_session', :domain => :all 

对于内部API调用

使用良好的共享密钥通过HTTPS连接进行身份validation。 在“授权”标头值中传递密码。

您可以轻松地将共享密钥与其他体系结构(如node.js)一起使用。 只需确保您始终使用HTTPS,否则可能会在网络上嗅探共享密钥。

您可以看一下2014年RailsConf期间Jeremy Green在Octolabs提出的面向服务的体系结构解决方案。

包含所有资源(回购,演示等)的博客文章位于: http : //www.octolabs.com/so-auth

解释所有内容的video在这里: http : //www.youtube.com/watch?v = L1B_HpCW8bs

这种集中式SSO并不是一项简单的任务,但Jeremy在谈论面向服务的体系结构方面做得非常出色,并准确地分享了如何将这个系统整合在一起。

我最近遇到了类似的问题,想要在Rails和Erlang应用程序之间共享会话数据。 我的解决方案是编写一个Rack::Session::Abstract::ID类,它将Redis中的会话存储为哈希值。 它不会在String类型上调用Marshal.dump 。 这允许非ruby应用程序使用某些会话值(如果它们具有session_id

 require 'rack/session/abstract/id' class MaybeMarshalRedisSession < Rack::Session::Abstract::ID def initialize(app, options = {}) @redis = options.delete(:redis) || Redis.current @expiry = options[:expire_after] ||= (60 * 60 * 24) @prefix = options[:key] || 'rack.session' @session_key = "#{@prefix}:%s" super end def get_session(env, sid) sid ||= generate_sid session = @redis.hgetall(@session_key % sid) session.each_pair do |key, value| session[key] = begin Marshal.load(value) rescue TypeError value end end [sid, session] end def set_session(env, sid, session, options={}) @redis.multi do session.each_pair do |key, value| # keep string values bare so other languages can read them value = value.is_a?(String) ? value : Marshal.dump(value) @redis.hset(@session_key % sid, key, value) end @redis.expire(@session_key % sid, @expiry) end sid end def destroy_session(env, sid, option={}) @redis.del(@session_key % sid) generate_sid unless options[:drop] end end 

你可以在rails中使用它:

  MyApp::Application.config.session_store MaybeMarshalRedisSession 

从机架到:

  use MaybeMarshalRedisSession 

并从其他地方:

 redis.hgetall("rack.session:#{session_id}") 

如果您想从MainApp或Node.js调用PhotoApp,您可以发出包含用户会话cookie的HTTP请求。