我有一個帶有用戶名和密碼的Spring登錄表單,它指向/ myapp/j_spring_security_check。如何在Spring獲取之前捕獲Spring Security登錄表單?
我希望能夠在Spring獲取請求之前提交登錄表單時攔截表單提交。
基本上,我希望能夠審查用戶輸入,看看它是否符合某些要求。如果沒有,應用程序將把用戶帶回登錄表單。如果用戶輸入滿足要求,那麼流程將進入Spring認證。
我該怎麼做?以有效的方式?
謝謝!
我有一個帶有用戶名和密碼的Spring登錄表單,它指向/ myapp/j_spring_security_check。如何在Spring獲取之前捕獲Spring Security登錄表單?
我希望能夠在Spring獲取請求之前提交登錄表單時攔截表單提交。
基本上,我希望能夠審查用戶輸入,看看它是否符合某些要求。如果沒有,應用程序將把用戶帶回登錄表單。如果用戶輸入滿足要求,那麼流程將進入Spring認證。
我該怎麼做?以有效的方式?
謝謝!
您可以使用常規的Spring Security功能來執行此操作。步驟如下:
實現自定義WebAuthenticationDetailsSource
和WebAuthenticationDetails
。 WebAuthenticationDetails
將捕獲您要驗證的額外表單域。
注:在Spring 3.0,您需要use a BeanPostProcessor to configure的WebAuthenticationDetailsSource
到UsernamePasswordAuthenticationFilter
。在Spring 3.1中,您可以直接在<form-login>
命名空間配置中執行此操作。
實現自定義AuthenticationProvider
和authenticate()
檢查WebAuthenticationDetails
,扔AuthenticationException
如果驗證失敗。在你的登錄頁面檢查這個異常。
或者,你可以創建一個Filter
,做您的驗證和春季安全過濾器之前添加。
ericacm,非常感謝您的意見。我的意圖是使用像過濾器。當請求到達authenticate()方法時,我沒有有效的方法在字段下顯示特定的錯誤消息。我可以在authenticate()內引發異常,但這並不夠具體。 基本上,我想將登錄表單作爲其他Spring-MVC來處理,如果存在驗證錯誤,則會在該字段下顯示一條消息。 我試過Filter方法,但是它似乎沒有辦法讓我把錯誤消息放在請求範圍內。 有什麼想法?謝謝! – curious1 2012-01-28 15:58:55
如果您使用第一種方法(步驟1和2),那麼您可以使用'((AuthenticationException)session.getAttribute(AbstractAuthenticationProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY))。getMessage()'在登錄頁面中獲取錯誤消息。 – sourcedelica 2012-01-28 19:21:18
當然你可以用'Filter'做同樣的事情,在會話中放入異常。 – sourcedelica 2012-01-29 13:31:00
使用上面的答案作爲指導,這是我創建的後處理器的一個工作示例,它允許您指定要提供給驗證器的登錄表單變量以及檢查terms_of_service複選框值的示例自定義驗證器在登錄表單中。
在Spring配置:
<bean id="authFormDetailsPostProcessor" class="com.sefaira.authauth.AuthFormDetailsPostProcessor">
<property name="formVarNames" value="terms_of_service_accepted"/>
</bean>
AuthFormDetailsPostProcessor.java:
public class AuthFormDetailsPostProcessor implements BeanPostProcessor {
private String [] formVarNames;
public void setFormVarNames (String formVarNames) {
this.formVarNames = formVarNames.split (",");
}
public static class Details extends WebAuthenticationDetails {
private Map<String, String> map;
public Details (HttpServletRequest request, String [] parameters) {
super (request);
this.map = new HashMap<String, String>();
for (String parameter : parameters) {
this.map.put (parameter.trim(), request.getParameter (parameter.trim()));
}
}
public String get (String name) {
return map.get(name);
}
}
public Object postProcessAfterInitialization(Object bean, String name) {
if (bean instanceof UsernamePasswordAuthenticationFilter) {
((UsernamePasswordAuthenticationFilter)bean).setAuthenticationDetailsSource(
new AuthenticationDetailsSource() {
public Object buildDetails(Object context) {
if (formVarNames == null) {
throw new RuntimeException ("AuthFormDetailsPostProcessor bean requires a formVarNames property, specifying a comma-delimited list of form vars to provide in the details object.");
}
return new Details ((HttpServletRequest) context, formVarNames);
}
});
}
return bean;
}
public Object postProcessBeforeInitialization(Object bean, String name) {
return bean;
}
}
這是使用它的定製身份驗證:
public class AuthServiceAuthenticator implements AuthenticationProvider {
@Override
public Authentication authenticate (Authentication authentication) throws AuthenticationException {
String email = (String) authentication.getPrincipal();
String password = (String) authentication.getCredentials();
AuthFormDetailsPostProcessor.Details details = (AuthFormDetailsPostProcessor.Details) authentication.getDetails();
// see if they checked the terms_of_service checkbox
String termsOfServiceVar = details.get ("terms_of_service_accepted");
boolean termsOfServiceAccepted = (termsOfServiceVar != null && termsOfServiceVar.equals ("on"));
// ... do your custom authentication ...
return authentication; // or a new authentication object
}
@Override
public boolean supports(Class<? extends Object> authentication) {
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
}
}
這個鏈接可以幫助 HTTP: //tejakantamneni.wordpress.com/2008/08/23/spring-securit y-using-custom-authentication-processing-filter/ – 2012-01-27 07:27:28