2016-12-27 30 views
2

我試圖總結我的Spring Security框架頭,並使用自定義AuthenticationProvider春天的認證而進行兩次,第一次成功後失敗

當我瀏覽到安全的網址,並用正確的憑據登錄表單,二實施認證嘗試登錄。第一次成功,第二次失敗,瀏覽器停留在登錄頁面,沒有錯誤信息。

這是我的安全配置。

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 

登錄當試圖用無效憑證(比ASDF其他密碼的任何東西)登錄時,進行身份驗證只有一次,並失敗,因爲它應該。

爲什麼認證在表單登錄時執行了兩次,第一次成功,然後失敗?有些配置錯誤,或者我錯過了一些bean?另外,我是否應該手動管理SecurityContext,使用自定義AuthenticationProvider實現時,還是Spring仍然在管理它?

我也很困惑,爲什麼我必須明確註釋userDetailsService方法爲@Bean,以便Spring可以管理,即使WebSecurityConfigurer聲明瞭此方法。

+0

你有沒有其他代碼可以改變'authentication'?我可以解釋爲什麼兩次,但不知道爲什麼第二次失敗。 – 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','UsernamePasswordAuthenticationToken'重寫'setAuthenticated'方法,並引發異常。 – chaoluo

相關問題