2011-12-30 17 views
18

Chúng tôi đang sử dụng bảo mật mùa xuân 3.0.5, Java 1.6 và Tomcat 6.0.32. Trong tập tin cấu hình .xml, chúng tôi đã có:Làm cách nào để có được tên người dùng từ thông tin đăng nhập không thành công khi sử dụng bảo mật mùa xuân?

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

authenticationFailureHandler chúng tôi định nghĩa là:

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

Vì vậy, chúng tôi đang chỉ đạo tất cả BadCredentialsExceptions đến index.htmlIndexController. Trong số IndexController Tôi muốn nhận được username đã được sử dụng cho lần đăng nhập không thành công. Tôi có thể làm cái này như thế nào?

Trả lời

20

Được rồi, vậy câu trả lời hóa ra là một điều cực kỳ đơn giản nhưng theo như tôi có thể nói, không được thảo luận hay ghi chép nhiều.

Dưới đây là tất cả những gì phải làm (không cấu hình bất cứ nơi nào vừa tạo lớp này) ...

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 + "]"); 
    } 
} 

Tôi xa một chuyên gia về an ninh mùa xuân vì vậy nếu ai đọc này và biết một lý do chúng tôi shouldn Làm như thế này hoặc biết cách tốt hơn tôi muốn nghe về nó.

+0

Tôi đã thử nhưng nó không hoạt động –

+0

Chúng tôi có mã chính xác này hoạt động trong thiết lập của chúng tôi. Tôi không thể cho bạn biết tại sao nó sẽ không hoạt động trong bạn. Chúng tôi không phải định cấu hình bất kỳ điều gì mới cũng như không thay đổi bất kỳ tệp .xml nào ở bất kỳ đâu. Các chú thích dường như chỉ vào mùa xuân tại mã này và thực hiện nó khi có một thông tin đăng nhập xấu. Nó hoạt động hoàn hảo cho chúng ta. – kasdega

+0

có thể nó yêu cầu một số cấu hình khác. Nhân tiện, tôi đã tìm ra một giải pháp thay thế. Cảm ơn bạn đã cung cấp thông tin, mặc dù :) –

5

Thay vào đó, bạn có thể cung cấp phiên bản DefaultAuthenticationEventPublisher của riêng mình và ghi đè phương thức publishAuthenticationFailure.

+0

bạn có ví dụ về điều này bạn có thể chỉ cho tôi không? – kasdega

+1

Bạn cần phải dây trong quá trình triển khai của chủ sở hữu. Xem bạn có thể mở rộng DefaultAuthenticationEventPublisher không. Sau đó, dây trong ProviderManager (đó là một thực hiện AuthenticationManager, mà bạn cần phải khai báo trong Spring Security). Lớp đó có phương thức setAuthenticationEventPublisher. – Saish

1

Tôi đã tìm thấy điều này phù hợp với tôi. Thật không may, tôi vẫn không tìm được vị trí chính xác của việc này trong các tài liệu SpringSecurity:

Trong bất kỳ hành động, bạn có thể kiểm tra tên người dùng cuối sử dụng (không có vấn đề gì đăng nhập được thất bại hay không):

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

UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY là hằng số tương ứng với tên thuộc tính. Nó hiện không còn được dùng nữa. – mrbaboo

+0

@mrbaboo: vì vậy đó là lý do tại sao tôi không thể tìm thấy bất cứ điều gì về hằng số này. Vì vậy, nó không được chấp nhận, bạn có biết cách nào khác để đạt được hiệu quả tương tự không? –

+2

Chỉ muốn chỉ ra rằng mã đã lưu trữ giá trị không được chấp nhận này trong phiên đã bị xóa trong bản phát hành Spring Security 3.1.0. Bạn sẽ phải sử dụng một trong các phương pháp khác được mô tả ở trên nếu bạn muốn đạt được hiệu ứng này với các phiên bản gần đây. – Jules

10

tôi đã làm nó theo cách này:

  1. tạo một lớp mà kéo dài SimpleUrlAuthenticationFailureHandler

  2. Overrid phương pháp onAuthenticationFailure, wh ich nhận được thông số HttpServletRequest.

  3. request.getParameter("username"), trong đó "username" là tên đầu vào của tôi ở dạng HTML của tôi.

+1

Nó hoạt động tốt, chỉ cần một bình luận, nếu bạn đang sử dụng tên mặc định trong các hình thức cho các văn bản đầu vào đó là ** j_username ** thì bạn phải Catch nó như thế này. 'request.getParameter (" j_username ")'. – OJVM

1

Hiện không có vẻ được nhiều thông tin về giải pháp này, nhưng nếu bạn thiết lập failureForwardUrl trong cấu hình Spring bảo mật thì bạn sẽ được chuyển đến trang lỗi thay vì chuyển hướng. Sau đó bạn có thể dễ dàng truy xuất tên người dùng và mật khẩu. Ví dụ, trong cấu hình của bạn thêm: .and().formLogin().failureForwardUrl("/login/failed") (* url phải khác với các url trang đăng nhập)

Và trong điều khiển đăng nhập của bạn, sau đây:

@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 là tên mặc định , nhưng bạn cũng có thể đặt chúng trong FormLoginConfigurer:

.and().formLogin().usernameParameter("email").passwordParameter("password").failureForwardUrl("/login/failed") 
Các vấn đề liên quan