2010-04-05 72 views
19

我想跟蹤用戶何時登錄到我的應用程序。我有一些代碼,我想在用戶通過身份驗證後立即執行。問題是,我無法弄清楚應該在哪裏調用。春季安全有沒有辦法在認證後調用方法?Spring-Security:認證後的調用方法

回答

4

只需編寫您自己的SpringSecurityFilter並在調用身份驗證提供程序後立即將其添加到過濾器鏈中。

package my.code; 

public class AuditFilter extends SpringSecurityFilter { 

    public void doFilterHttp(...) throws ... { 
     {application code to run before request is processed} 
     chain.doFilter(...); 
     {application code to run after request has fully processed} 
    } 
} 
配置中的XML

然後(無論你設置安全過濾器鏈)加上這樣一行:

<bean id="auditFilter" class="my.code.AuditFilter> 
    <security:custom-filter position="LAST"/> <-- you can change the position 
</bean> 
+0

請注意,SpringSecurityFilter改爲通用Spring的web GenericFilterBean Spring Security的3 – 2013-01-22 13:51:16

11

最好的方法是創建一個應用程序偵聽器並使用spring安全上下文進行註冊。

import org.springframework.context.ApplicationListener; 
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent; 

public class AuthenticationSuccessListener implements ApplicationListener<InteractiveAuthenticationSuccessEvent> { 

    @Override 
    public void onApplicationEvent(InteractiveAuthenticationSuccessEvent event) { 
     System.out.println("User Logged In"); 

    } 
} 

確保添加上面的類彈簧security.xml文件作爲一個bean。還有很多其他類型的安全事件偵聽器可以偵聽,請檢查類型層次結構以查看可以偵聽的所有安全事件類型的列表。

+0

視情況而定,但這通常是我的出路。如果您需要創建身份驗證事件的副作用,請使用ApplicationListener。如果您需要指定如何處理認證過程,請使用處理程序。在這種情況下,「跟蹤認證行動」,我會去參加這個活動,它更像是一種副作用。 – wooki 2015-10-11 22:24:29

30

可能會是有用的人...... 在Spring 3的情況下,配置安全:

<security:http use-expressions="true" auto-config="true"> 
    <security:intercept-url pattern="..."/> 
    <security:form-login 
      authentication-failure-handler-ref="authFailureHandler" 
      authentication-success-handler-ref="authSuccessHandler"/> 
    <security:logout success-handler-ref="logoutSuccessHandler" 
      invalidate-session="true"/> 
    <security:session-management session-fixation-protection="newSession"/> 
</security:http> 

<bean id="authFailureHandler" class="mine.AuthenticationFailureHandlerImpl"/> 
<bean id="authSuccessHandler" class="mine.AuthenticationSuccessHandlerImpl"/> 
<bean id="logoutSuccessHandler" class="mine.LogoutSuccessHandlerImpl"/> 

和實施適當的類:

public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler { 

    @Override 
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { 
     //do what you want with 
     response.getOutputStream().write("success".getBytes()); 
    } 
} 

您可以通過該XML鏈接資源配置。

+1

好東西!感謝您的身份驗證 - 成功處理程序 - 參考號 – 2013-01-23 09:30:50

+0

如果我想添加一個小動作,然後繼續正常處理,它將如何? – DiegoSahagun 2015-12-10 14:05:35

6

如果您想繼續默認行爲,但只是在執行自己的業務邏輯之間,您可能會在返回之前extend SimpleUrlAuthenticationSuccessHandler並調用super.onAuthenticationSuccess(request, response, authentication);。更多詳情,請參閱https://stackoverflow.com/a/6770785/418439

+0

這就是我通常所做的事情,而且我建議您也這麼做,如果您不需要在原始實現中更改任何內容,只需要附加功能即可。我創建了一個ChainAuthenticationSuccessHandler,然後它會調用我的自定義處理程序和一個像SimpleUrlAuthenticationSuccessHandler這樣的現有處理程序。我發現它比擴展Spring的課程更可靠和乾淨。我想你也可以在原始處理程序的頂部創建某種裝飾器類以避免繼承,但是鏈式解決方案對我更有吸引力。 – wooki 2015-10-11 22:34:21

1

Authentication沒有一定意味着成功登錄。用戶可以通過例如雙向SSL(X.509證書)成功進行身份驗證,如果會話併發管理設置爲max-sessions="1",並且這是第二次併發登錄嘗試,Spring Security仍會將您重定向到錯誤頁面。如果你的設置很簡單,沒有會話併發控制,你可以假設login = authentication用於所有實際目的。否則,如果您有,例如,邏輯記錄每個登錄數據庫中的每個,您將不得不在實際登錄點處調用此邏輯,而不是在身份驗證點。做到這一點的一種方法(絕不是最佳的,受我對Spring Security框架理解有限),要實現你自己的ConcurrentSessionControlAuthenticationStrategy(點擊here獲取源代碼),並將它注入到您的Spring Security(3.2及更高版本)的CompositeSessionAuthenticationStrategy中,配置XML:

<http> 
    . 
    . 
    <session-management session-authentication-strategy-ref="sas" /> 
    . 
    . 
</http> 
. 
. 
<beans:bean id="sas" class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy"> 
    <beans:constructor-arg> 
     <beans:list> 
      <beans:bean class="path.to.my.implementation.of.ConcurrentSessionControlAuthenticationStrategy"> 
       <beans:constructor-arg ref="sessionRegistry"/> 
       <beans:property name="maximumSessions" value="1"/> 
       <beans:property name="exceptionIfMaximumExceeded" value="true"/> 
      <beans:bean> 
      <beans:bean class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy"/> 
      <beans:bean class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy"/> 
       <beans:constructor-arg ref="sessionRegistry"/> 
      </beans:bean> 
     </beans:list> 
    </beans:constructor-arg> 
</beans:bean> 

<beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/> 

我寧願注入定製PostLogin處理程序進入該框架的ConcurrentSessionControlAuthenticationStrategy,而不是複製粘貼,從它變成我的自定義ConcurrentSessionControlAuthenticationStrategy並進行修改時,但我不知道的方式目前要做到這一點。

可以找到更完整的配置示例here

2

如果你想避免讀取所有的線程:具有註釋&多一點解釋策劃版本:

import org.springframework.context.ApplicationListener; 
import org.springframework.security.authentication.event.AuthenticationSuccessEvent; 
import org.springframework.security.core.userdetails.User; 
import org.springframework.stereotype.Component; 

@Component 
public class LoginSuccessListener implements ApplicationListener<AuthenticationSuccessEvent{ 

    @Override 
    public void onApplicationEvent(AuthenticationSuccessEvent evt) { 

     // if you just need the login 
     String login = evt.getAuthentication().getName(); 
     System.out.println(login + " has just logged in"); 

     // if you need to access full user (ie only roles are interesting -- the rest is already verified as login is successful) 
     User user = (User) evt.getAuthentication().getPrincipal(); 
     System.out.println(user.getUsername() + " has just logged in"); 

    } 
} 
相關問題