3

顧客が要求する機能を実装するのに苦労しています。要するに、彼らは、管理者側を介して、選択した顧客をアプリケーションからログアウトできるようにしたいと考えています。アプリケーションはFlexをフロントエンド技術として使用し、AMF経由でサーバーにアクセスしています。サーバー側は、Spring Security と Spring BlazeDS Integration を使用しています。

基本的には、Spring Security および/または Spring BlazeDS Integration は、すぐに使用できるセッション管理 (および強制終了) のための集中型システムを提供しますか?

概念実証の目的で、次のコードを使用して、すべてのユーザーをログアウトし、すべてのセッションを強制終了しようとしました。

package xxx.xxx.xxx;

import java.util.List;

import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.userdetails.User;

import flex.messaging.MessageBroker;
import flex.messaging.security.LoginCommand;

public class SessionServiceImpl {
    private static final Log log = LogFactory.getLog(SessionServiceImpl.class);

    private SessionRegistry sessionRegistry;
    private MessageBroker messageBroker;

    public SessionRegistry getSessionRegistry() {
        return sessionRegistry;
    }

    @Autowired
    public void setSessionRegistry(SessionRegistry sessionRegistry) {
        log.debug("sessionregistry set");
        this.sessionRegistry = sessionRegistry;
    }    

    public MessageBroker getMessageBroker() {
        return messageBroker;
    }

    @Autowired
    public void setMessageBroker(MessageBroker messageBroker) {
        log.debug("messagebroker set");
        this.messageBroker = messageBroker;
    }

    public void logoutUser(String userName) {
        log.debug("Logging out user by username: "+userName);
        List<Object> principals = null;
        if(sessionRegistry != null){
            principals = sessionRegistry.getAllPrincipals();
        }else{
            log.debug("sessionRegistry null");
        }

        if(principals != null){
            for (Object object : principals) {
                User user = (User)object;

                // get single users all sessions
                List<SessionInformation> sessions = sessionRegistry.getAllSessions(user, false);
                log.debug("Sessions list size: "+sessions.size());


                if(messageBroker != null){
                    LoginCommand command = messageBroker.getLoginManager().getLoginCommand();
                    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(user, user.getPassword());
                    command.logout(usernamePasswordAuthenticationToken);

                    for (SessionInformation sessionInformation : sessions) {
                        log.debug(ReflectionToStringBuilder.toString(sessionInformation));
                        sessionInformation.expireNow();
                        sessionRegistry.removeSessionInformation(sessionInformation.getSessionId());
                    }

                }else{
                    log.debug("messageBroker null");
                }

                if(object != null){
                    log.debug(ReflectionToStringBuilder.toString(object));
                }else{
                    log.debug("object null");
                }

            }
        }else{
            log.debug("principals null");
        }
    }
}

残念ながら、上記のコードは機能しません。私が知る限り、これは次の 2 つの理由によるものです。

A) LoginCommand は「アプリケーション全体」ではなく、現在のセッションに関連付けられているため、現在のセッション (管理者が使用しているセッション) のみをログアウトしようとし、他のセッションを無視します。

B) sessionInformation.expireNow() はセッションを期限切れにしようとしますが、セッションが無効になる前にユーザーがなんとかリクエストを作成した場合、セッションは破棄されません

ドキュメントから、セッションが session.invalidate() によって直接無効化される可能性があることがわかりますが、すべてのセッション オブジェクトにアクセスする方法がないようです。

この種の機能を実装するための最速または最もスマートな方法は何ですか?

よろしく、ジュッカ

4

2 に答える 2

0

私のアプローチは、間接的なセッションの無効化を行うことです。

ConcurrentSessionControl セキュリティ オプションを使用して、ユーザーごとに 1 つのセッションを制限します。ユーザーがマークされているかどうかを確認し、必要に応じてセッションを無効にするカスタム SessionAuthenticationStrategy を記述します。たとえば、usernamepassword フィルターが新しいセッションを作成する前に、セッション戦略を実行する必要があることに注意してください。

ユーザー名を保持するために、データベースまたは静的クラスのようなものを使用できます。さらに、おそらく、セッションがマークされてから x 分後にセッションを無効にする、ある種のタイムスタンプも必要になるでしょう。

まったく別のアプローチは、サーブレット セッション リスナーを実装することです。これは、すべてのログイン セッションを user->session マップに記録し、必要に応じてそれらを無効にすることができます。

Bean を接続する方法については、リファレンス マニュアルを参照してください http://docs.spring.io/spring-security/site/docs/3.0.x/reference/session-mgmt.html

于 2013-10-07T16:19:56.103 に答える