簡體   English   中英

在 Spring 安全性中捕獲 Remember-Me 身份驗證事件

[英]Catching Remember-Me Authentication Events in Spring Security

我正在開發一個應用程序,我需要在其中捕獲並響應身份驗證事件以采取適當的措施。 目前,當用戶手動登錄時,我可以很好地捕捉到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();
        }
    }
}

附加信息:

我在原始帖子中沒有提到在 Map 中存儲 Session Id 和身份驗證 object 的要求是因為我使用的是 Google 地球插件。 GE 充當一個單獨的、不相關的用戶代理,因此用戶的 session 信息永遠不會被 GE 傳遞給服務器。 出於這個原因,我重寫了來自 GE 的請求 URL 以包含用戶的活動 Session Id(來自上述地圖)作為參數,因此我們可以驗證所述 Z71C7AE294B7ABD866B3FB295B3B9 確實對登錄用戶有效。 所有這一切都已到位,因為我們擁有 GE 需要的 KML,但我們不能允許用戶通過 Firebug 或您擁有的直接獲取未受保護的 URL。

Spring 配置:(抱歉,格式有點捏造)

<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>

請閱讀這篇文章底部的更新

您是否嘗試過基於“InteractiveAuthenticationSuccessEvent 的事件實例”添加另一個“else if”?

    @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 地球插件)在我的網站上顯示為使用另一個 http 客戶端(用戶的瀏覽器)登錄的人?” 即使您可以讓它發揮作用,從安全角度來看,這似乎也不是一個好主意。 另一個有趣的問題是,“除了讓插件通過 http 請求 KML 文件之外,我如何將 KML 加載到 Google 地球插件中?” 根據他們的文檔,有一個方法,parsekml(),它接受一個包含 KML 數據的字符串。 因此,理論上您可以使用來自用戶瀏覽器的 JavaScript/AJAX 調用加載受保護的 KML 數據,這將與您網站的正常安全設置兼容,然后將返回的 KML 傳遞給 parsekml()。

根據spring 文檔,“在 Spring 安全 3 中,用戶首先由 AuthenticationManager 進行身份驗證,一旦成功通過身份驗證,就會創建 Z21D6F40CFB511982E44Z7E0E250A955”。

相反,您可以實現自己的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 在身份驗證過程中調用此 class。 就是這樣:

第 1 步:自定義由<form-login>元素創建的UsernamePasswordAuthenticationFilter 特別是,將其放入您的<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。 本質上,由於資源所有者授權,您正在向客戶端發出訪問令牌。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM