2017-01-18 4 views
0

すべての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); 
    } 
} 

感謝!!

答えて

0

私はこの問題を発見しました。

まず、認証マネージャーを設定する正しい方法は、antMatcherが存在しないため、上記の設定方法ではないため、私のリソースとページが誰にでも公開されました。

第2に、無限のリダイレクトとエラー405を引き起こした問題は、投稿を受け入れるようにフィルタを定義していないことでした。

これを修正した後、私のJSPログインフォームと認証メカニズムは正常に機能しましたが、「/ api」はリソースではなくログインページにリダイレクトされていました。

最後に、http.formLogin()UsernamePasswordAuthenticationFilterを作成しています。私はそれらの2つを持っています - ログインごとに1つ。だから私はhttp.addFilterBefore()をログインごとに別のURLで追加しなければならなかった。 "/ api" URLは、私が定義したものの代わりにSpringのデフォルトのリダイレクトを再度使用していたので、それらを上書きしなければなりませんでした。

セキュリティ設定:

@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 { 

     //LDAP Stuff 

     TicketAndLDAPAuthenticationProvider ticketAndLDAPAuthenticationProvider = new TicketAndLDAPAuthenticationProvider(authenticator,authoritiesPopulator); 
     auth.authenticationProvider(ticketAndLDAPAuthenticationProvider); 

     LdapAuthenticationProvider ldapAuthenticationProvider = new LdapAuthenticationProvider(authenticator,authoritiesPopulator); 
     auth.authenticationProvider(ldapAuthenticationProvider);  
    } 

    //Management Endpoints Authorization 
    @Configuration 
    @Order(1) 
    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(2) 
    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"; 

     protected void configure(HttpSecurity http) throws Exception { 
      /*CSRF configuration*/ 
      http.csrf().disable(); 

      http.addFilterBefore(new TicketAndLDAPAuthenticationFilter(LOGIN_PATH,authSuccessHandler,authFailureHandler), UsernamePasswordAuthenticationFilter.class); 

      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() 
        .logout().permitAll() 
         .logoutSuccessHandler(logoutSuccessHandler); 

      http 
        .authorizeRequests().anyRequest().authenticated(); 

     } 
    } 

    //JSP Authentication+Authorization 
    @Configuration 
    @Order(3) 
    public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { 

     private String LOGIN_PATH = "/login.htm"; 

     @Override 
     protected void configure(HttpSecurity http) throws Exception { 
      /*CSRF configuration*/ 
      http.csrf().disable(); 

      http.addFilterBefore(new TicketAndLDAPAuthenticationFilter(LOGIN_PATH), UsernamePasswordAuthenticationFilter.class); 

      /*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_PATH).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(); 
     } 
    } 
} 

およびフィルタ:

public class TicketAndLDAPAuthenticationFilter extends AbstractAuthenticationProcessingFilter { 

    public TicketAndLDAPAuthenticationFilter(String defaultProcessUrl) { 
     super(new AntPathRequestMatcher(defaultProcessUrl, "POST")); 
    } 

    public TicketAndLDAPAuthenticationFilter(String defaultProcessUrl, AuthenticationSuccessHandler authenticationSuccessHandler, AuthenticationFailureHandler authenticationFailureHandler) { 
     super(new AntPathRequestMatcher(defaultProcessUrl, "POST")); 
     setAuthenticationFailureHandler(authenticationFailureHandler); 
     setAuthenticationSuccessHandler(authenticationSuccessHandler); 
    } 

    @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"); 

     if (username==null || password==null) { 
      return null; 
     } 

     TicketAndLDAPAuthenticationToken token = new TicketAndLDAPAuthenticationToken(username,password,null); 

     return token; 
    } 
} 

これらは私のために働いている設定やフィルタです

関連する問題