How to catch Spring Security login form before Spring receives?

I have a Spring login form with a username and password that points to / myapp / j _spring_security_check.

I hope to intercept form submission when someone submits a registration form before Spring receives the request.

Basically, I hope you can look at user input to see if it meets certain requirements. If this is not the case, the application will return the user to the login form. If user input meets the requirements, then the flow proceeds to Spring authentication.

How can i do this? Effective way?

Thanks!

+4
source share
2 answers

You can do this using the usual Spring security features. Steps:

  • Implement custom WebAuthenticationDetailsSource and WebAuthenticationDetails . WebAuthenticationDetails will capture additional form fields that you want to validate.

    Note: In Spring 3.0, you need to use BeanPostProcessor to configure WebAuthenticationDetailsSource in UsernamePasswordAuthenticationFilter . In Spring 3.1, you can do this directly in the <form-login> namespace configuration.

  • Deploy custom AuthenticationProvider and in authenticate() check WebAuthenticationDetails by throwing an AuthenticationException if validation is not completed. On the login page, check for this exception.

Alternatively, you can create a Filter that does your validation and add it before the Spring Security filter.

+2
source

Using the above answer as a guide, this is a working example that I created from a postprocessor that allows you to specify which login form variables to provide for the authenticator, and a user authenticator example that checks the value of the terms_of_service flag in the login form.

In the Spring configuration:

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

This is a custom Authenticator that uses it:

 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)); } } 
0
source

Source: https://habr.com/ru/post/1393290/


All Articles