Ruby on rails 跨应用程序/服务器的Rails身份验证
我一直在开发我的rails应用程序,同时尽可能使它们模块化。我试图在下面实现不同的部分作为服务 举个Facebook的例子:Ruby on rails 跨应用程序/服务器的Rails身份验证,ruby-on-rails,ruby,authentication,oauth,single-sign-on,Ruby On Rails,Ruby,Authentication,Oauth,Single Sign On,我一直在开发我的rails应用程序,同时尽可能使它们模块化。我试图在下面实现不同的部分作为服务 举个Facebook的例子: a) 一个MainApp,允许用户拥有墙、帖子等。 b) 存储照片、允许用户查看其照片等的PhotoApp。这是一个独立的应用程序,将具有一个REST API,MainApp也可以使用该API 我曾考虑将OAuth用作单一登录解决方案(如本教程中所述),其中每个应用程序都将通过OAuth进行授权,并将基于cookie访问当前用户会话 第一个问题:这是可行的解决方案吗 第二
a) 一个MainApp,允许用户拥有墙、帖子等。
b) 存储照片、允许用户查看其照片等的PhotoApp。这是一个独立的应用程序,将具有一个REST API,MainApp也可以使用该API 我曾考虑将OAuth用作单一登录解决方案(如本教程中所述),其中每个应用程序都将通过OAuth进行授权,并将基于cookie访问当前用户会话 第一个问题:这是可行的解决方案吗 第二个问题:我希望能够从MainApp服务器(而不是用户浏览器)调用PhotoAppAPI。在这种情况下,身份验证将如何工作
第三个问题:如果说我有一个使用node.js的服务,这将如何工作?我最近遇到了一个类似的问题,希望在Rails和Erlang应用程序之间共享会话数据。我的解决方案是编写一个
Rack::Session::Abstract::ID
类,将会话作为哈希值存储在Redis中。它不调用String
类型上的Marshal.dump
。这允许非ruby应用程序使用一些会话值(如果它们具有session\u 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
从机架,带有:
use MaybeMarshalRedisSession
以及来自其他地方的:
redis.hgetall("rack.session:#{session_id}")
如果要从MainApp或Node.js调用PhotoApp,可以发出包含用户会话cookie的HTTP请求 是的,使用OAuth的SSO是一个可行的解决方案,但它不是最简单的解决方案。当建造任何新的东西时,这是一条路要走。OAuth标准涵盖了很多领域 OAuth的主要优点是它允许用户向第三方应用程序提供访问其帐户的权限,而无需向第三方透露密码。如果您没有认真地提供这种互操作性,那么OAuth可能有些过分 鉴于复杂性,我提供了一对不同的解决方案: 用于单点登录 诀窍是在域内的主机之间共享会话ID cookie&使用共享会话存储(如ActiveRecordStore或基于缓存的存储) 每个Rails应用程序都有一个用于签署cookie的“秘密”。在较新的Rails应用程序中,它位于
/config/initializers/secret\u token.rb
中。在每个应用程序中设置相同的秘密令牌
然后,将会话配置为允许从所有子域进行访问:
AppName::Application.config.session_store :active_record_store, :key => '_app_name_session', :domain => :all
用于内部API调用
使用良好的共享机密通过HTTPS连接进行身份验证。在“Authorization”头值中传递秘密
您可以轻松地将共享秘密与其他体系结构(如node.js)一起使用。只要确保您始终使用HTTPS,否则共享机密可能会在网络上被嗅探。您可以看看Octolabs的Jeremy Green在2014年RailsConf期间提出的面向服务的体系结构解决方案 包含所有资源(回购、演示等)的博文位于以下位置: 下面是解释一切的视频:
这种集中化的SSO不是一项简单的任务,但Jeremy在讨论面向服务的体系结构和准确地共享如何将此系统组合在一起方面做得非常出色。有一些可能有助于实现这种场景。共享会话ID似乎是SSO的一个良好开端,但到此为止。这里遗漏了大量的实现细节。应用程序在登录期间如何进行身份验证?应用程序是如何了解已登录用户的功能的?是的,在实施完整的SSO解决方案时,有很多东西需要设计。创建一个中央身份验证服务可能是一个良好的开端,但这并不是StackOverflow的答案。。。可能更像是一本O'Reilly的书。这假设所有域共享一个公共tld/子域。那么不同的TLD呢?这个答案并不是“假设”服务器都在同一个域中,而是明确地声明了这一事实(在“For Single Sign On.”下),如果服务器分布在不同的域中,那么您需要研究更复杂的解决方案,如OAuth或SAML-SSO。
AppName::Application.config.session_store :active_record_store, :key => '_app_name_session', :domain => :all