2016-12-27 15 views
2

私は春のセキュリティフレームワークの周りに私の頭をラップし、AuthenticationProvider春認証が最初に成功し、2回実施し、その後、失敗し

私はセキュリティで保護されたURLと、正しい資格情報を使用してフォーム・ログインに移動し、2つのカスタムを使用して認証を実装しようとしていますログイン試行が行われます。最初は成功し、2番目は失敗し、ブラウザはエラーメッセージなしでログインページにとどまります。

ここに私のセキュリティ設定があります。

package training2; 

{ imports... } 

@Configuration 
@EnableWebSecurity 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

    @Autowired 
    @Qualifier("myProvider") 
    private AuthenticationProvider provider; 

    @Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
     auth.authenticationProvider(provider); 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http.authorizeRequests() 
      .anyRequest().authenticated() 
      .and() 
      .formLogin() 
      .permitAll() 
      .and() 
      .logout() 
      .permitAll(); 
    } 

    @Override 
    public UserDetailsService userDetailsServiceBean() throws Exception { 
     // TODO Auto-generated method stub 
     return super.userDetailsServiceBean(); 
    } 

    @Override 
    @Bean 
    protected UserDetailsService userDetailsService() { 
     return new UserDetailsService() { 

      public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException { 
       System.out.println("loadUserByUsername"); 

       return new UserDetails() { 

        private static final long serialVersionUID = -1044116648365271684L; 

        public boolean isEnabled() { 
         // TODO Auto-generated method stub 
         return true; 
        } 

        public boolean isCredentialsNonExpired() { 
         // TODO Auto-generated method stub 
         return true; 
        } 

        public boolean isAccountNonLocked() { 
         // TODO Auto-generated method stub 
         return true; 
        } 

        public boolean isAccountNonExpired() { 
         // TODO Auto-generated method stub 
         return true; 
        } 

        public String getUsername() { 
         // TODO Auto-generated method stub 
         return username; 
        } 

        public String getPassword() { 
         // TODO Auto-generated method stub 
         return "asdf"; 
        } 

        public Collection<? extends GrantedAuthority> getAuthorities() { 
         // TODO Auto-generated method stub 
         return null; 
        } 
       }; 
      } 
     }; 
    } 

    @Bean 
    @Qualifier("myProvider") 
    public AuthenticationProvider myProvider(final UserDetailsService userDetailsService) { 
     return new AuthenticationProvider() { 

      public boolean supports(Class<?> authentication) { 
       return true; 
      } 

      public Authentication authenticate(Authentication authentication) throws AuthenticationException { 
       System.out.println("authenticate"); 

       UserDetails user = userDetailsService.loadUserByUsername(authentication.getName()); 
       if (user != null && user.getPassword().equals(authentication.getCredentials())) { 
        System.out.println("authentication ok"); 
        return authentication; 
       } else { 
        System.out.println("authentication failed"); 
        throw new AuthenticationException(null) { 
         private static final long serialVersionUID = -1022654748424786317L; 
        }; 
       } 
      } 
     }; 
    } 
} 

そして次は、有効な資格情報

authenticate 
loadUserByUsername 
authentication ok 
authenticate 
loadUserByUsername 
authentication failed 

にログインしようとすると、無効な資格情報(空自以外のパスワード何でも)でログインしようとするとき、認証が行われ、コンソールにプリントアウトされます一度だけ、失敗する必要があります。

なぜ、フォームのログイン時に2回認証が行われるのですか?最初に成功してから失敗します。何かが間違って設定されているのですか?また、カスタムAuthenticationProviderの実装を使用する場合は、SecurityContextを手動で管理する必要がありますか、それともSpringがそれを管理していますか?

私はまた、がこのメソッドを宣言しているにもかかわらず、メソッドを明示的に注釈しなければならない理由は、@BeanがSpring管理であるためです。

+0

「認証」を変更した他のコードはありますか?理由を2回説明することはできますが、2回目の失敗が失敗する理由はわかりません。 – chaoluo

答えて

1
.anyRequest().authenticated() 

だから、認証がFilterSecurityInterceptorに認証されているかどうかをチェックしますが、あなたのプロバイダに返さ認証は、認証されていない、FilterSecurityInterceptorは再びauthenticateを行います。

if (user != null && user.getPassword().equals(authentication.getCredentials())) { 
    System.out.println("authentication ok"); 
    // should authenticated authenticaiton 
    //return new UsernamePasswordAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) 
} 
+0

setAuthenticatedをtrueに設定すると、次の例外がスローされました。java.lang.IllegalArgumentException:このトークンを、GrantedAuthorityリストを代用するトラステッドコンストラクターに設定できません。新しいUsernameAndPasswordAuthenticationTokenを返すことで問題は解決しましたが、私はそのロジックを理解していません。とにかく認証にフラグが必要な理由と例外がスローされた理由 –

+0

はい、認証済みの認証を新規にする必要があります。古い認証には資格情報が含まれているためです。 – chaoluo

+0

あなたのプロジェクトで認証が 'UsernamePasswordAuthenticationToken'で、' UsAuthamePasswordAuthenticationToken'が 'setAuthenticated'メソッドをオーバーライドし、例外をスローします。 – chaoluo

関連する問題