2

複数のテナントをサポートする Spring Social アプリケーションを構築しています。アプリケーションは、URL に基づいてテナントを識別します (例: tenant1.example.com と tenant2.example.com)。アプリケーションのユーザーが Facebook や Twitter を使用して接続できるようにしたいと考えています。私が抱えている問題は、各テナントが独自のビジネスであり、独自の独自の Facebook および Twitter 資格情報セットを持っていることです。ConnectionFactoryRegistry に複数の Facebook ConnectionFactory インスタンスまたは複数の Twitter ConnectionFactory インスタンスを含めることはできないと思います。たとえば、これは機能しません。

ConnectionFactoryRegistry registry = new ConnectionFactoryRegistry();
registry.addConnectionFactory(new FacebookConnectionFactory("tenant1ClientId", "tenant1ClientSecret"));
registry.addConnectionFactory(new FacebookConnectionFactory("tenant2ClientId", "tenant2ClientSecret"));

Spring Social のドキュメントによると、ロケーターは単一のインスタンスを返すため、上記は機能しません。

public interface ConnectionFactoryLocator {
   ConnectionFactory<?> getConnectionFactory(String providerId);
   <A> ConnectionFactory<A> getConnectionFactory(Class<A> apiType);

   Set<String> registeredProviderIds();
}   

ConnectInterceptor を作成し、preConnect() ステップで提供された ConnectionFactory インスタンスに関連するテナント資格情報を挿入することを考えましたが、connectionFactory インスタンスが共有されているため、マルチスレッド Web アプリケーションでは機能しないと思われます。

そこで、次に考えたのは、テナントごとに一意の ConnectionFactoryRegistry インスタンスを単純に作成することでした。それは上記の問題を解決します。

しかし、問題は ConnectController (Spring の OAuth ダンス コントローラー) に移ります。アプリケーションは 1 つのコントローラーしか持つことができず、コントローラーは 1 つのレジストリーしか保持できないため、テナントに基づいて適切なレジストリーを使用するようにコントローラーに指示するにはどうすればよいでしょうか?

テナントごとに一意の ConnectionFactory インスタンスをサポートするマルチテナント Spring Social アプリケーションを構築する正しい方法は何ですか? 理想的には、XML で ConnectionFactory インスタンスを定義したくありません。それらは動的で DB に格納されるからです。

4

2 に答える 2

1

私は、CustomConnectionFactoryRegistry を作成することで同様にうまくいき、より下流の問題に取り組むことを発見しました。以下ツイッターの例。このソリューションは、データ リポジトリに依存して、キャッシュされているアプリケーション テナントと providerId の oauth 資格情報を取得します。

public class CustomConnectionFactoryRegistry implements ConnectionFactoryLocator {

    @Autowired
    private ConnectServiceRepository connectServiceRepository; // get the credentials for the tenant

    private final Map<Class<?>, String> apiTypeIndex = new HashMap<Class<?>, String>();

    public CustomConnectionFactoryRegistry(){
        apiTypeIndex.put(Twitter.class, "twitter");
    }

    @Override
    public ConnectionFactory<?> getConnectionFactory(String providerId) {
        OAuthApp app = connectServiceFactory.getProviderApp(providerId);
        if (app == null) {
            throw new IllegalArgumentException("No connection factory for service provider '" + providerId + "' is registered");
        }
        OAuth1ConnectionFactory<?> twitterConnectionFactory = new TwitterConnectionFactory(app.getApiKey(),app.getApiSecret());

        return twitterConnectionFactory;        
    }

    @Override
    @SuppressWarnings("unchecked")
    public <A> ConnectionFactory<A> getConnectionFactory(Class<A> apiType) {
        String providerId = apiTypeIndex.get(apiType);
        if (providerId == null) {
            throw new IllegalArgumentException("No connection factory for API [" + apiType.getName() + "] is registered");
        }
        return (ConnectionFactory<A>) getConnectionFactory(providerId);
    }

}
于 2014-08-22T17:49:10.967 に答える
1

私は過去に同様の問題に直面しました。Spring Social + 多言語サイト (example.de、example.fr、...) => 複数の Facebook アプリ (Facebook アプリではユーザーを同じドメインにのみ返すことができるため)。最終的に、ConnectController のカスタム バージョン (実際には ProviderSignInController でした) と 1 つのヘルパー クラス (名前、ConnectionSupport などについてはわかりません) を作成し、実行時に適切な FacebookConnectionFactory を選択できるようにしました。

于 2013-07-08T09:15:05.860 に答える