7

適切なアクションを実行するために認証イベントをキャッチして応答する必要があるアプリケーションを開発しています。AuthenticationSuccessEvent現在、ユーザーが手動でログインしたときにSpringがスローする問題をうまく捉えています。現在、Remember-Me機能を実装しようとしています。ロギングは、私がキャッチしたいInteractiveAuthenticationSuccessEventイベントがであるかを理解するのに役立ちました。誰かが以下のコードをざっと見て、この新しいイベントに対応するのを手伝ってもらえますか?

@Override
public void onApplicationEvent(ApplicationEvent event) {
    log.info(event.toString()); // debug only: keep track of all events
    if (event instanceof AuthenticationSuccessEvent) {
        AuthenticationSuccessEvent authEvent = (AuthenticationSuccessEvent)event;
        lock.writeLock().lock();
        try {
            sessionAuthMap.put(((WebAuthenticationDetails)authEvent.getAuthentication().getDetails()).getSessionId(), authEvent.getAuthentication());
        } finally {
            lock.writeLock().unlock();
        }
    } else if (event instanceof HttpSessionDestroyedEvent) {
        HttpSessionDestroyedEvent destroyEvent = (HttpSessionDestroyedEvent)event;
        lock.writeLock().lock();
        try {
            sessionAuthMap.remove(destroyEvent.getId());
        } finally {
            lock.writeLock().unlock();
        }
    }
}

追加情報:

元の投稿では、セッションIDと認証オブジェクトをマップに保存する必要があるのは、GoogleEarthプラグインを使用しているためだとは述べていませんでした。GEは、独立した無関係のユーザーエージェントとして機能するため、ユーザーのセッション情報がGEによってサーバーに渡されることはありません。このため、GEからのリクエストURLを書き換えて、ユーザーのアクティブなセッションID(前述のマップから)をパラメーターとして含め、そのセッションIDがログインしたユーザーに対して実際に有効であることを確認できるようにします。GEが必要とするKMLがあるため、これらすべてが整っていますが、ユーザーがFirebugまたはあなたが持っているものを介して直接の保護されていないURLを取得することを許可することはできません。

Spring Config :(申し訳ありませんが、フォーマットを少し曖昧にしました)

<sec:http use-expressions="true">
<sec:intercept-url pattern="/Login.html*" access="permitAll"/>
<sec:intercept-url pattern="/j_spring_security*" access="permitAll" method="POST"/>
<sec:intercept-url pattern="/main.css*" access="permitAll"/>
<sec:intercept-url pattern="/favicon.ico*" access="permitAll"/>
<sec:intercept-url pattern="/images/**" access="permitAll"/>
<sec:intercept-url pattern="/common/**" access="permitAll"/>
<sec:intercept-url pattern="/earth/**" access="permitAll"/>
<sec:intercept-url pattern="/earth/kml/**" access="permitAll"/>
<sec:intercept-url pattern="/earth/js/**" access="permitAll"/>
<sec:intercept-url pattern="/css/**" access="permitAll"/>   
<sec:intercept-url pattern="/resource*" access="permitAll"/>
<sec:intercept-url pattern="/geom*" access="hasRole('ROLE_SUPERUSER')"/>    
<sec:intercept-url pattern="/status/**" access="permitAll"/>    
<sec:intercept-url pattern="/index.html*" access="hasRole('ROLE_USER')"/>
<sec:intercept-url pattern="/project.html*" access="hasRole('ROLE_USER')"/>
<sec:intercept-url pattern="/js/**" access="hasRole('ROLE_USER')"/>
<sec:intercept-url pattern="/help/**" access="hasRole('ROLE_USER')"/>
<sec:intercept-url pattern="/app/**" access="hasRole('ROLE_USER')"/>
<sec:intercept-url pattern="/data/**" access="hasRole('ROLE_USER')"/>   
<sec:intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')"/> 
<sec:intercept-url pattern="/session/**" access="hasRole('ROLE_USER')"/>
<sec:intercept-url pattern="/" access="hasRole('ROLE_USER')"/>
<sec:intercept-url pattern="/**" access="denyAll"/>
<sec:intercept-url pattern="**" access="denyAll"/>

<sec:session-management session-fixation-protection="none" />

<sec:form-login login-page="/Login.html${dev.gwt.codesrv.htmlparam}" default-target-url="/index.html${dev.gwt.codesrv.htmlparam}" authentication-failure-url="/Login.html${dev.gwt.codesrv.htmlparam}"/>
<sec:http-basic/>
<sec:logout invalidate-session="true" logout-success-url="/Login.html${dev.gwt.codesrv.htmlparam}"/>
 <sec:remember-me key="[REMOVED]" />
 </sec:http>

<bean id="authenticationEventPublisher" class="org.springframework.security.authentication.DefaultAuthenticationEventPublisher" />

<bean id="org.springframework.security.authenticationManager" class="org.springframework.security.authentication.ProviderManager">
    <property name="authenticationEventPublisher" ref="authenticationEventPublisher"/>
    <property name="providers">
        <list>
            <ref bean="authenticationProvider" />
            <ref bean="anonymousProvider" />
        </list>
    </property>
</bean>

<bean id="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
    <property name="passwordEncoder" ref="passwordEncoder"/>
    <property name="saltSource" ref="saltSource"/>
    <property name="userDetailsService" ref="userService" />
</bean>

<bean id="anonymousProvider" class="org.springframework.security.authentication.AnonymousAuthenticationProvider">
    <property name="key" value="[REMOVED]" />
</bean>
4

2 に答える 2

4

この投稿の下部にある更新をお読みください

「InteractiveAuthenticationSuccessEventのイベントインスタンス」に基づいて別の「elseif」を追加してみましたか?

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
    log.info(event.toString()); // debug only: keep track of all events
    if (event instanceof AuthenticationSuccessEvent) {
        AuthenticationSuccessEvent authEvent = (AuthenticationSuccessEvent)event;
        lock.writeLock().lock();
        try {
            sessionAuthMap.put(((WebAuthenticationDetails)authEvent.getAuthentication().getDetails()).getSessionId(), authEvent.getAuthentication());
        } finally {
            lock.writeLock().unlock();
        }
    } else if (event instanceof InteractiveAuthenticationSuccessEvent) {
        InteractiveAuthenticationSuccessEvent authEvent = (InteractiveAuthenticationSuccessEvent)event;
        lock.writeLock().lock();
        try {
            sessionAuthMap.put(((WebAuthenticationDetails)authEvent.getAuthentication().getDetails()).getSessionId(), authEvent.getAuthentication());
        } finally {
            lock.writeLock().unlock();
        }
    } else if (event instanceof HttpSessionDestroyedEvent) {
        HttpSessionDestroyedEvent destroyEvent = (HttpSessionDestroyedEvent)event;
        lock.writeLock().lock();
        try {
            sessionAuthMap.remove(destroyEvent.getId());
        } finally {
            lock.writeLock().unlock();
        }
    }
}

更新:あなたの質問は基本的に、「あるhttpクライアント(つまり、Google Earthプラグイン)を、別のhttpクライアント(ユーザーのブラウザー)を使用してログインした人として自分のサイトに認証されているように見せることはできますか?」です。それを機能させることができたとしても、セキュリティの観点からは良い考えとは思えません。もう1つの興味深い質問は、「プラグインにhttp経由でKMLファイルをリクエストさせる以外に、KMLをGoogle Earthプラグインに読み込むにはどうすればよいですか?」です。彼らのドキュメントによると、KMLデータを含む文字列を受け取るメソッドparsekml()があります。したがって、理論的には、ユーザーのブラウザからJavaScript / AJAX呼び出しを使用して保護されたKMLデータを読み込むことができます。これは、サイトの通常のセキュリティ設定と互換性があり、返されたKMLをparsekml()に渡します。

于 2011-08-17T01:47:10.433 に答える
2

Springのドキュメントによると、「Spring Security 3では、ユーザーは最初にAuthenticationManagerによって認証され、正常に認証されると、セッションが作成されます。」

代わりに、独自に実装することもできますAuthenticationSuccessHandler(おそらくサブクラス化することによってSavedRequestAwareAuthenticationSuccessHandler)。メソッドには任意のロジックを配置できるonAuthenticationSuccessため、既存のロジックをそこに移動します。

public class MyAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
    // declare and initialize lock and sessionAuthMap at some point...
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, 
            HttpServletResponse response, Authentication authentication) 
            throws ServletException, IOException {
        lock.writeLock().lock();
        try {
            sessionAuthMap.put(request.getSession().getId(), authentication);
        } finally {
            lock.writeLock().unlock();
        }
        super.onAuthenticationSuccess(request, response, authentication);
    }
}

次に、認証プロセス中にSpring Securityがこのクラスを呼び出すように、構成を更新します。方法は次のとおりです。

ステップ1:要素UsernamePasswordAuthenticationFilterによって作成されるをカスタマイズし<form-login>ます。<http>特に、これを要素に入れます。

<sec:custom-filter position="FORM_LOGIN_FILTER" ref="myFilter" />

ステップ2:myFilterを定義し、それにフックMyAuthenticationSuccessHandlerします。

<bean id="myFilter" 
    class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
    <property name="authenticationManager" ref="authenticationManager" />
    <property name="authenticationFailureHandler" ref="myAuthenticationSuccessHandler" />
    <property name="authenticationSuccessHandler" ref="myAuthenticationFailureHandler" />
</bean>

<bean id="myAuthenticationSuccessHandler" 
    class="my.MyAuthenticationSuccessHandler">
<!-- set properties here -->
</bean>

<!-- you can subclass this or one of its parents, too -->
<bean id="myAuthenticationFailureHandler" 
    class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
    <!-- set properties such as exceptionMappings here -->
</bean>

詳細については、http://static.springsource.org/spring-security/site/docs/3.0.x/reference/ns-config.htmlを参照してください。AbstractAuthenticationProcessingFilterのドキュメントも参照してください。

ところで、あなたの問題は私にOAuthを思い出させます。基本的に、リソース所有者の承認の結果として、クライアントにアクセストークンを発行します。

于 2011-08-24T15:16:02.493 に答える