Hallo an alle Spring-Experten!AbstractAuthenticationProcessingFilter wird nicht ausgelöst vor UsernamePasswordAuthenticationFilter
Ich habe ein Problem, das ich versuche, für eine Weile zu lösen, aber ich denke, dass ich eine Sackgasse erreicht habe.
Also im Grunde, was ich brauche, ist meine Spring-Security zu konfigurieren (in Spring-Boot), zwei Authentifizierungsmechanismen (eine für Legacy JSP-Seiten und eine für REST-APIs) zu haben. So folgte ich dem folgenden Beitrag: multiple authentication mechanisms in a single app using java config
Es funktionierte gut mit einem LDAP-Authentifizierungsanbieter. Aber dann habe ich versucht, meine LDAP-Verbindung zu erweitern, um auch ein Ticket von einem Drittanbieter-Dienst zu erhalten (der für zukünftige Verbindungen mit anderen Diensten verwendet wird), und dort hatte ich ein Problem.
Also habe ich einen neuen Authentication Token-, Filter- und Authentifizierungsanbieter erstellt, aber der Standard UsernamePasswordAuthenticationFilter
wird zuerst ausgelöst, egal was ich mache.
Ich habe versucht, diesem Beitrag How to configure a custom filter programatically in Spring Security? zu folgen und sah, dass das Problem in der Tatsache sein könnte, dass mein Filter UsernamePasswordAuthenticationFilter
verlängert wurde. Also habe ich das entfernt und versucht, eine einfache AbstractAuthenticationProcessingFilter
zu haben, immer noch - kein Glück.
Ich denke, das Problem ist in meiner WebSecurity-Konfiguration. Derzeit, mit dem folgenden Code werde ich teilen, die REST Api-Authentifizierung ist zurück 405 - Methode nicht erlaubt und das Legacy Login steckt in einer Endlosschleife und stürzt ab, noch bevor ich "Login" klicke.
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) //Enables @PreAuthorize on methods
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private LDAPConfigurationBean ldapBean;
@Autowired
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
//HERE GOES LDAP CONNECTION STUFF
// Add the custom LDAP + Token provider to the Authentication provider chain
auth.authenticationProvider(new TicketAndLDAPAuthenticationProvider(authenticator,authoritiesPopulator));
// Creating an LDAP provider using the authenticator and the populator.
auth.authenticationProvider(new LdapAuthenticationProvider(authenticator,authoritiesPopulator));
}
@Configuration
@Order(1)
public static class ConfigureFilters extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.addFilterBefore(new TicketAndLDAPAuthenticationFilter(),UsernamePasswordAuthenticationFilter.class);
}
}
//Management Endpoints Authorization
@Configuration
@Order(2)
public static class EndpointsWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/manage/health")
.authorizeRequests()
.anyRequest().permitAll();
}
}
//API Authentication+Authorization
@Configuration
@Order(3)
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Autowired
private RestAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
private RestAuthSuccessHandler authSuccessHandler;
@Autowired
private RestAuthFailureHandler authFailureHandler;
@Autowired
private RestLogoutSuccessHandler logoutSuccessHandler;
private String LOGIN_PATH = "/api/authenticate";
private String USERNAME = "username";
private String PASSWORD = "password";
protected void configure(HttpSecurity http) throws Exception {
/*CSRF configuration*/
http.csrf().disable();
http
.antMatcher(LOGIN_PATH)
.authorizeRequests()
.anyRequest().permitAll();
http
.antMatcher("/api/**")
//Stateless session creation - no session will be created or used by Spring Security
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.formLogin().permitAll()
.loginProcessingUrl(LOGIN_PATH)
.usernameParameter(USERNAME)
.passwordParameter(PASSWORD)
.successHandler(authSuccessHandler)
.failureHandler(authFailureHandler)
.and()
.logout().permitAll()
.logoutSuccessHandler(logoutSuccessHandler);
http
.authorizeRequests().anyRequest().authenticated();
}
}
//JSP Authentication+Authorization
@Configuration
@Order(4)
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
/*CSRF configuration*/
http.csrf().disable();
/*Static content*/
http
.authorizeRequests()
.antMatchers("/css*//**").permitAll()
.antMatchers("/images*//**").permitAll()
.antMatchers("/scripts*//**").permitAll()
.antMatchers("/fonts*//**").permitAll()
.antMatchers("/login*").anonymous();
/*Login/Logout configuration*/
http
.formLogin()
.loginPage("/login.htm").permitAll()
.defaultSuccessUrl("/index.htm?name=******")
.failureUrl("/login.htm?error=true")
.and()
.logout().permitAll()
.logoutSuccessUrl("/login.htm")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID");
/*URL roles authorizations*/
http
.authorizeRequests().anyRequest().authenticated();
}
}
}
Wie Sie sehen können, ich versuche meinen Filter in der „Configure Filters“ Methode zu konfigurieren - aber ich versucht habe es auch in dem Adapter zu konfigurieren, mit/ohne @Bean
Anmerkung - alles ohne Glück .
Filter:
public class TicketAndLDAPAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public TicketAndLDAPAuthenticationFilter() {
super("/*");
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
//Save the password for later
String username = request.getParameter("username");
String password = request.getParameter("password");
TicketAndLDAPAuthenticationToken token = new TicketAndLDAPAuthenticationToken(username,password,null);
return token;
}
}
Edit: vergessen haben, zu dem Filter hinzuzufügen:
if (request.getParameter("username") == null || request.getParameter("password") == null) == null) {
return null;
}
Jetzt bekomme ich 405 in beiden Login-Mechanismen.
Token:
public class TicketAndLDAPAuthenticationToken extends UsernamePasswordAuthenticationToken {
private AuthTicket otp;
private String restoredPassword;
public TicketAndLDAPAuthenticationToken(String username, String password, RestAuthLoginTicket otp) {
super(username, password);
this.otp = otp;
}
public AuthTicket getOTP() {
return otp;
}
public AuthTicket getOtp() {
return otp;
}
public void setOtp(AuthTicket otp) {
this.otp = otp;
}
}
Anbieter:
public class TicketAndLDAPAuthenticationProvider extends LdapAuthenticationProvider {
@Autowired
TokenUtils tokenUtils;
public TicketAndLDAPAuthenticationProvider(LdapAuthenticator authenticator, LdapAuthoritiesPopulator authoritiesPopulator) {
super(authenticator, authoritiesPopulator);
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
TicketAndLDAPAuthenticationToken token = (TicketAndLDAPAuthenticationToken) super.authenticate(authentication);
token.setOtp(tokenUtils.getTicket(token));
return token;
}
@Override
public boolean supports(Class<?> authentication) {
return TicketAndLDAPAuthenticationToken.class.isAssignableFrom(authentication);
}
}
Vielen Dank im Voraus !!