Quelle est l'équivalent Java pour Spring Security <custom-filter>
tag?
<http>
<custom-filter position="FORM_LOGIN_FILTER" ref="myFilter"/>
</http>
J'ai essayé
http.addFilter( new MyUsernamePasswordAuthenticationFilter() )
où la classe étend le filtre par défaut, mais elle utilise toujours la valeur par défaut formLogin
.
Mon filtre:
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter{
// proof of concept of how the http.addFilter() works
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
if (!request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
System.out.println("running my own version of UsernmePasswordFilter ... ");
String username = obtainUsername(request);
String password = obtainPassword(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
}
La pièce de configuration pertinente:
@Configuration
@EnableWebMvcSecurity // annotate class configuring AuthenticationManagerBuilder
@ComponentScan("com.kayjed")
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**","/signup").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
http.addFilter(new MyUsernamePasswordAuthenticationFilter());
}
...
}
L'exécution de l'application MVC dans le débogueur affiche toujours l'authentification des tentatives de connexion à partir de la valeur par défaut UsernamePasswordAuthenticationFilter
au lieu de mon intention d'employer la classe MyUsernamePasswordAuthenticationFilter
.
Quoi qu'il en soit, je n'essaie pas d'amener quelqu'un à déboguer du code; j'aimerais plutôt voir un bon exemple en utilisant Java qui exécute l'équivalent de l'élément de filtre personnalisé dans l'approche XML. La documentation est un peu laconique.
Quelques questions que vous devrez peut-être garder à l'esprit:
Votre filtre doit être ajouté avant la norme UsernamePasswordAuthenticationFilter
http.addFilterBefore(customUsernamePasswordAuthenticationFilter(),
UsernamePasswordAuthenticationFilter.class)
Si vous étendez UsernamePasswordAuthenticationFilter, votre filtre reviendra immédiatement sans rien faire sauf si vous définissez un RequestMatcher
myAuthFilter.setRequiresAuthenticationRequestMatcher(
new AntPathRequestMatcher("/login","POST"));
Toute la configuration que vous effectuez dans http.formLogin().x().y().z()
est appliquée à la norme UsernamePasswordAuthenticationFilter
et non au filtre personnalisé que vous créez. Vous devrez le configurer manuellement vous-même. L'initialisation de mon filtre d'authentification ressemble à ceci:
@Bean
public MyAuthenticationFilter authenticationFilter() {
MyAuthenticationFilter authFilter = new MyAuthenticationFilter();
authFilter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/login","POST"));
authFilter.setAuthenticationManager(authenticationManager);
authFilter.setAuthenticationSuccessHandler(new MySuccessHandler("/app"));
authFilter.setAuthenticationFailureHandler(new MyFailureHandler("/login?error=1"));
authFilter.setUsernameParameter("username");
authFilter.setPasswordParameter("password");
return authFilter;
}
Je ne trouve aucun problème dans ce code. Je pense que votre configuration est correcte. Le problème est ailleurs. J'ai un code similaire,
package com.programsji.config;
import Java.util.ArrayList;
import Java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import com.programsji.security.CustomAuthenticationProvider;
import com.programsji.security.CustomSuccessHandler;
import com.programsji.security.CustomUsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/js/**", "/css/**", "/theme/**").and()
.debug(true);
}
@Bean
public CustomUsernamePasswordAuthenticationFilter customUsernamePasswordAuthenticationFilter()
throws Exception {
CustomUsernamePasswordAuthenticationFilter customUsernamePasswordAuthenticationFilter = new CustomUsernamePasswordAuthenticationFilter();
customUsernamePasswordAuthenticationFilter
.setAuthenticationManager(authenticationManagerBean());
customUsernamePasswordAuthenticationFilter
.setAuthenticationSuccessHandler(customSuccessHandler());
return customUsernamePasswordAuthenticationFilter;
}
@Bean
public CustomSuccessHandler customSuccessHandler() {
CustomSuccessHandler customSuccessHandler = new CustomSuccessHandler();
return customSuccessHandler;
}
@Bean
public CustomAuthenticationProvider customAuthenticationProvider() {
CustomAuthenticationProvider customAuthenticationProvider = new CustomAuthenticationProvider();
return customAuthenticationProvider;
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
List<AuthenticationProvider> authenticationProviderList = new ArrayList<AuthenticationProvider>();
authenticationProviderList.add(customAuthenticationProvider());
AuthenticationManager authenticationManager = new ProviderManager(
authenticationProviderList);
return authenticationManager;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/reportspage").hasRole("REPORT")
.antMatchers("/rawdatapage").hasRole("RAWDATA").anyRequest()
.hasRole("USER").and().formLogin().loginPage("/login")
.failureUrl("/login?error")
.loginProcessingUrl("/j_spring_security_check")
.passwordParameter("j_password")
.usernameParameter("j_username").defaultSuccessUrl("/")
.permitAll().and().httpBasic().and().logout()
.logoutSuccessUrl("/login?logout").and().csrf().disable()
.addFilter(customUsernamePasswordAuthenticationFilter());
}
}
Cela fonctionne bien sur ma demande. vous pouvez télécharger l'intégralité de ce projet à partir de l'url: https://github.com/programsji/rohit/tree/master/UsernamePasswordAuthenticationFilter
Essayez d'ajouter @Component
à votre classe MyUsernamePasswordAuthenticationFilter
.
Cette annotation rend la classe considérée comme candidate à l'auto-détection, voir: @ Component
Pour ça:
<custom-filter position="FORM_LOGIN_FILTER" ref="myFilter"/>
Vous pouvez ajouter ceci:
.addFilter[Before|After](authenticationTokenProcessingFilter, UsernamePasswordAuthenticationFilter.class)