2016-05-10 84 views
3

此問題實際上與此問題problem有關。彈簧安全 - 自定義ExceptionTranslationFilter

根據@ harsh-poddar的建議,我添加了相應的過濾器。

但是,添加後似乎即使使用有效憑證我也無法登錄。

以下是相關的代碼:

SecurityConfig

@EnableWebSecurity 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

// @Bean 
// public CustomAuthenticationEntryPoint customAuthenticationEntryPoint() { 
//  return new CustomAuthenticationEntryPoint(); 
// } 

@Bean 
public CustomExceptionTranslationFilter customExceptionTranslationFilter() { 
    return new CustomExceptionTranslationFilter(new CustomAuthenticationEntryPoint()); 
} 

@Override 
protected void configure(HttpSecurity http) throws Exception { 
    http 
     //Note : Able to login without this filter, but after adding this, valid credential also fails 
     .addFilterAfter(customExceptionTranslationFilter(), ExceptionTranslationFilter.class) 
//  .exceptionHandling() 
//   .authenticationEntryPoint(new customAuthenticationEntryPoint()) 
//   .and() 
     .authorizeRequests() 
      .anyRequest().authenticated() 
      .and() 
     .requestCache() 
      .requestCache(new NullRequestCache()) 
      .and() 
     .httpBasic() 
      .and() 
     .csrf().disable(); 
} 

    @Autowired 
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 
     auth.authenticationProvider(new CustomAuthenticationProvider()); 
    } 
} 

CustomAuthenticationProvider

@Component 
public class CustomAuthenticationProvider implements AuthenticationProvider { 

public CustomAuthenticationProvider() { 
    super(); 
} 

@Override 
public Authentication authenticate(final Authentication authentication) throws AuthenticationException { 
    final String name = authentication.getName(); 
    final String password = authentication.getCredentials().toString(); 
    if (name.equals("admin") && password.equals("password")) { 
     final List<GrantedAuthority> grantedAuths = new ArrayList<>(); 
     grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER")); 
     final UserDetails principal = new User(name, password, grantedAuths); 
     final Authentication auth = new UsernamePasswordAuthenticationToken(principal, password, grantedAuths); 
     return auth; 
    } else { 
     throw new BadCredentialsException("NOT_AUTHORIZED"); 
    } 
} 

    @Override 
    public boolean supports(final Class<?> authentication) { 
     return authentication.equals(UsernamePasswordAuthenticationToken.class); 
    } 

} 

CustomExceptionTranslationFilter

@Component 
public class CustomExceptionTranslationFilter extends ExceptionTranslationFilter { 

    public CustomExceptionTranslationFilter(AuthenticationEntryPoint authenticationEntryPoint) { 
     super(authenticationEntryPoint); 
    } 
} 

CustomAuthenticationEntryPoint

public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint { 

    @Override 
    public void commence(HttpServletRequest request, HttpServletResponse response, 
      AuthenticationException authException) throws IOException, ServletException { 
     response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized."); 
    } 
} 

P/S:很抱歉的基本問題,我在春天&春季安全真正的新。

+0

看到我的回答在previos問題http://stackoverflow.com/questions/37063342/spring-security-with-restcontroller-jsonish-customauthenticationprovider-resp/37063583#37063583 – D0dger

+0

@ D0dger:謝謝你給出的答案。但仍然有同樣的錯誤。使用有效憑證登錄也會觸發「AuthExceptionEntryPoint」。任何提示我可以在哪裏檢查以調試? – lxnx

+0

打開org.springframework.security'包的日誌記錄並將其附加到問題中(當有效憑據不起作用時) – D0dger

回答

3

AuthenticationEntryPoint的預期設計是啓動/發起認證。但是,您的實施CustomAuthenticationEntryPoint不會這樣做。相反,它只是發回未經授權的迴應。有關實現細節的更多詳細信息,請參閱javadoc的AuthenticationEntryPoint

根據您的配置,您正在使用HTTP基本身份驗證:

protected void configure(HttpSecurity http) throws Exception { 
    http 
     .authorizeRequests() 
      .anyRequest().authenticated() 
      .and() 
     .httpBasic(); 
} 

這具體配置會自動配置BasicAuthenticationEntryPoint這是AuthenticationEntryPoint的實現。根據server protocolBasicAuthenticationEntryPoint將挑戰用戶的http響應頭部WWW-Authenticate: Basic realm="User Realm"進行身份驗證。

但是,事實上你正在配置你自己的CustomAuthenticationEntryPoint它最終會覆蓋BasicAuthenticationEntryPoint這不是你想要做的。

other post推薦這種配置,這又不是你想要做的。

protected void configure(HttpSecurity http) throws Exception { 
    http 
     .authorizeRequests() 
      .anyRequest().authenticated() 
      .and() 
     .httpBasic() 
      .and() 
     .exceptionHandling().authenticationEntryPoint(new CustomAuthenticationEntryPoint()); 
} 

如果你的主要目標是在驗證失敗比我建議有配置AuthenticationFailureHandler形式登錄配置,以向用戶提供自定義響應。下面是配置:

http 
    .authorizeRequests() 
     .anyRequest().authenticated() 
     .and() 
    .formLogin().failureHandler(new DefaultAuthenticationFailureHandler()) 
     .and() 
    .csrf().disable(); // NOTE: I would recommend enabling CSRF 

你實現DefaultAuthenticationFailureHandler是:

public class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandler { 

    @Override 
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { 
     // Set status only OR do whatever you want to the response 
     response.setStatus(HttpServletResponse.SC_FORBIDDEN); 
    } 
} 

AuthenticationFailureHandler是專門用來處理認證嘗試失敗。

+0

感謝您的建議。我試過這個,發現每個請求都被重定向(302)爲「/ login」。對於您的信息,這是通過@RestController進行的Web服務通信。 – lxnx