すべてのSpring Expertに感謝!UsernamePasswordAuthenticationFilterの前にAbstractAuthenticationProcessingFilterが起動していません
私はしばらく解決しようとしている問題がありますが、私は枯れてしまったと思います。
基本的に私が必要とするのは、2つの認証メカニズム(1つは従来のJSPページ用、もう1つはREST API用)を持つようSpring Security(Spring-Bootで)を構成することです。だから私は次のポストに従った: multiple authentication mechanisms in a single app using java config
それは、1つのLDAP認証プロバイダとうまくいった。しかし、LDAP接続を拡張して、サードパーティのサービス(別のサービスへの将来の接続に使用される)からチケットを取得しようとしましたが、そこに問題がありました。
私は新しい認証トークン、フィルタ、および認証プロバイダを作成しましたが、私が何をしていてもデフォルトでUsernamePasswordAuthenticationFilter
が最初に起動されています。
私はこのポストHow to configure a custom filter programatically in Spring Security?に従おうとしましたが、問題は私のフィルタがUsernamePasswordAuthenticationFilter
を拡張していたことにあるかもしれません。だから私はこれを取り除き、単純なAbstractAuthenticationProcessingFilter
、まだ - 運がないようにしようとしました。
問題はWebSecurityの設定にあると思います。現在、次のコードで共有しようとしていますが、REST API認証が返されます405 - 方法が許可されていませんと "Login"を押す前に、従来のログインが無限ループに陥ってクラッシュします。
@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();
}
}
}
あなたが見ることができるように、私は「フィルタを設定」の方法で私のフィルタを設定しようとしている - と@Bean
注釈なし/が、私はまた、アダプターの内部でそれを設定しようとした - すべての運で。
フィルタ:
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;
}
}
編集:は、フィルタに追加するのを忘れ:
if (request.getParameter("username") == null || request.getParameter("password") == null) == null) {
return null;
}
は今、私は両方のログイン・メカニズムで405を取得します。
トークン:
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;
}
}
プロバイダ:事前に
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);
}
}
感謝!!