2011-12-30 5 views
18

Używamy zabezpieczeń Spring 3.0.5, Java 1.6 i Tomcat 6.0.32. W naszym pliku konfiguracyjnego .xml mamy:Jak mogę uzyskać nazwę użytkownika po nieudanym logowaniu za pomocą wiosennego zabezpieczenia?

<form-login login-page="/index.html" default-target-url="/postSignin.html" always-use-default-target="true" 
authentication-failure-handler-ref="authenticationFailureHandler"/> 

i naszą authenticationFailureHandler zdefiniowany jako:

<beans:bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler"> 
    <beans:property name="exceptionMappings"> 
     <beans:props> 
    <beans:prop key="org.springframework.security.authentication.BadCredentialsException">/index.html?authenticationFailure=true</beans:prop> 
    </beans:props> 
    </beans:property> 
</beans:bean> 

Java

@RequestMapping(params={"authenticationFailure=true"}, value ="/index.html") 
    public String handleInvalidLogin(HttpServletRequest request) { 
     //... How can I get the username that was used??? 
     // I've tried: 
     Object username = request.getAttribute("SPRING_SECURITY_LAST_USERNAME_KEY"); 
     Object username = request.getAttribute("SPRING_SECURITY_LAST_USERNAME"); // deprecated 
    } 

więc jesteśmy kierowanie całą BadCredentialsExceptions do index.html i IndexController. W wersji IndexController chciałbym uzyskać username, który został użyty do nieudanej próby logowania. Jak mogę to zrobić?

Odpowiedz

20

OK, więc odpowiedź okazała się czymś niezwykle prostym, ale z tego, co wiem, nie omawianym ani nie udokumentowanym.

Oto wszystko, co musiałem zrobić (nie ma nigdzie tylko konfiguracje utworzone z tej klasy) ...

import org.apache.log4j.Logger; 
import org.springframework.context.ApplicationListener; 
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent; 
import org.springframework.stereotype.Component; 

@Component 
public class MyApplicationListener implements ApplicationListener<AuthenticationFailureBadCredentialsEvent> { 
    private static final Logger LOG = Logger.getLogger(MyApplicationListener.class); 

    @Override 
    public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent event) { 
     Object userName = event.getAuthentication().getPrincipal(); 
     Object credentials = event.getAuthentication().getCredentials(); 
     LOG.debug("Failed login using USERNAME [" + userName + "]"); 
     LOG.debug("Failed login using PASSWORD [" + credentials + "]"); 
    } 
} 

jestem daleko od eksperta bezpieczeństwa wiosna więc jeśli ktoś to czyta i wie, z powodu shouldn Zrób to w ten sposób lub znasz lepszy sposób, który chciałbym o tym usłyszeć.

+0

Próbowałem, ale to nie działa –

+0

Mamy dokładnie ten kod działający w naszej konfiguracji. Nie mogę ci powiedzieć, dlaczego to nie zadziałałoby w twoim. Nie musieliśmy konfigurować niczego nowego ani zmieniać żadnego pliku .xml w dowolnym miejscu. Adnotacje wydają się wskazywać wiosną na ten kod i uruchamiać go, gdy wystąpi zły login. Działa to doskonale dla nas. – kasdega

+0

może to wymaga innej konfiguracji. Przy okazji, znalazłem alternatywne rozwiązanie. Dziękuję za informację, ale :) –

5

Zamiast tego można podać własną wersję DefaultAuthenticationEventPublisher i zastąpić metodę publishingAuthenticationFailure.

+0

czy masz przykład tego, na co możesz mnie wskazać? – kasdega

+1

Powinieneś podłączyć się do implementacji właściciela. Sprawdź, czy możesz rozszerzyć DefaultAuthenticationEventPublisher. Następnie podłącz do dostawcy ProviderManager (który jest implementacją AuthenticationManager, który musisz zadeklarować w Spring Security). Ta klasa ma metodę setAuthenticationEventPublisher. – Saish

1

Znalazłem, że to działa dla mnie. Niestety, nadal nie znaleziono dokładnego położenia tego w dokumentach SpringSecurity:

W każdym działaniu, można sprawdzić ostatnio używane nazwy użytkownika (bez względu na logowanie się powiodło, czy nie):

String username = (String) request.getSession().getAttribute("SPRING_SECURITY_LAST_USERNAME"); 
+1

UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY jest stałą, która odpowiada nazwie atrybutu. Jest teraz przestarzałe. – mrbaboo

+0

@mrbaboo: dlatego nie mogę znaleźć nic na temat tej stałej. Więc jest przestarzały, czy znasz alternatywny sposób osiągnięcia tego samego efektu? –

+2

Chciałem tylko wskazać, że kod przechowujący tę wycofaną wartość w sesji został usunięty w wersji 3.1.0 Spring Security. Będziesz musiał użyć jednej z innych metod opisanych powyżej, jeśli chcesz osiągnąć ten efekt w najnowszych wersjach. – Jules

10

zrobiłem to w ten sposób:

  1. utworzono klasę, która rozciąga SimpleUrlAuthenticationFailureHandler

  2. Overrid przy czym sposób onAuthenticationFailure, WH ich otrzymuje jako parametr parametr HttpServletRequest.

  3. request.getParameter("username"), gdzie "username" to nazwa mojego wpisu w moim formularzu HTML.

+1

To działa dobrze, tylko komentarz, jeśli używasz domyślnej nazwy w formularzu dla tekstu wejściowego, który jest ** j_username **, to musisz Złap to tak. 'request.getParameter (" j_username ")'. – OJVM

1

Nie wydaje się być dużo informacji na temat tego rozwiązania, ale jeśli ustawisz failureForwardUrl w konfiguracji Wiosna Bezpieczeństwa, zostanie przekazany do strony błędu zamiast przekierowany. Następnie można łatwo pobrać nazwę użytkownika i hasło. Na przykład w config dodać: .and().formLogin().failureForwardUrl("/login/failed") (* URL musi być różny od adresu URL strony logowania)

A w kontrolerze logowania, co następuje:

@RequestMapping(value = "/login/failed") 
public String loginfailed(@ModelAttribute(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_USERNAME_KEY) String user, @ModelAttribute(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_PASSWORD_KEY) String password) { 
    // Your code here 
} 

SPRING_SECURITY_FORM_USERNAME_KEY, SPRING_SECURITY_FORM_PASSWORD_KEY są nazwy domyślne , ale możesz je również ustawić w formularzu Log View:

.and().formLogin().usernameParameter("email").passwordParameter("password").failureForwardUrl("/login/failed") 
Powiązane problemy