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;
}
}
这是使用它的自定义Authenticator:
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));
}
}
2 回答
您可以使用常规Spring Security功能执行此操作 . 步骤是:
WebAuthenticationDetails
将捕获您要验证的额外表单字段 .Note: 在Spring 3.0中,您需要use a BeanPostProcessor to configure
WebAuthenticationDetailsSource
进入UsernamePasswordAuthenticationFilter
. 在Spring 3.1中,您可以直接在<form-login>
命名空间配置中执行此操作 .AuthenticationProvider
并在authenticate()
中检查WebAuthenticationDetails
,如果验证失败则抛出AuthenticationException
. 在您的登录页面中检查此例外 .或者,您可以创建一个
Filter
进行验证并在Spring Security过滤器之前添加它 .使用上面的答案作为指导,这是我创建的一个后处理器的工作示例,它允许您指定要向验证器提供的登录表单变量,以及一个示例自定义验证器,用于检查登录表单中的terms_of_service复选框值 .
在Spring配置中:
AuthFormDetailsPostProcessor.java:
这是使用它的自定义Authenticator: