30

Railsアプリを可能な限りモジュール化しながら開発してきました。その下にあるさまざまな部分をサービスとして実装しようとしています。

Facebookの例を挙げてみましょう。a
)ユーザーが壁や投稿などを持てるようにするMainApp。b
)写真を保存し、ユーザーが自分の写真を見ることができるようにするPhotoApp。これは MainAppでも使用できるRESTAPI。

私はOAuthをシングルサインオンソリューションとして使用することを考えていました(このチュートリアルのようにhttp://blog.joshsoftware.com/2010/12/16/multiple-applications-with-devise-omniauth-and-single-sign-on /)各アプリはOAuthを介して承認され、Cookieに基づいて現在のユーザーセッションにアクセスします。

最初の質問:これは実行可能な解決策ですか?

2番目の質問:(ユーザーのブラウザーからではなく) MainAppサーバーからPhotoAppAPIを呼び出せるようにしたいこの状況で認証はどのように機能しますか?

3番目の質問: node.jsを使用するサービスがあるとしたら、これはどのように機能しますか?

4

3 に答える 3

20

はい、OAuthを使用したSSOは実行可能なソリューションですが、最も単純なソリューションではありません。新しいものを構築するときは、OAuth2.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接続を介して認証するには、適切な共有シークレットを使用します。「Authorization」ヘッダー値でシークレットを渡します。

共有シークレットは、他のアーキテクチャ(node.jsなど)で簡単に使用できます。常にHTTPSを使用していることを確認してください。そうしないと、共有シークレットがネットワーク上で盗聴される可能性があります。

于 2012-11-03T17:54:49.517 に答える
4

2014年のRailsConf中にOctolabsでJeremyGreenによって提案されたサービス指向アーキテクチャソリューションを見ることができます。

すべてのリソース(リポジトリ、デモなど)を含むブログ投稿は次の場所にあります:http ://www.octolabs.com/so-auth

そして、すべてを説明するビデオはここにあります:http ://www.youtube.com/watch?v=L1B_HpCW8bs

この一元化されたSSOは簡単な作業ではありませんが、Jeremyは、サービス指向アーキテクチャーについて話し、このシステムをどのように組み合わせるかを正確に共有するという素晴らしい仕事をしました。

于 2015-01-18T16:06:31.770 に答える
3

最近、RailsとErlangアプリの間でセッションデータを共有したいという同様の問題が発生しました。私の解決策は、Rack::Session::Abstract::IDセッションをハッシュ値としてRedisに保存するクラスを作成することでした。タイプMarshal.dumpは必要ありません。Stringこれにより、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

これは、次のレールから使用できます。

 MyApp::Application.config.session_store MaybeMarshalRedisSession

ラックから:

 use MaybeMarshalRedisSession

そして他の場所から:

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

MainAppまたはNode.jsからPhotoAppを呼び出す場合は、ユーザーのセッションCookieを含むHTTPリクエストを作成できます。

于 2012-11-03T05:45:16.407 に答える