2016-07-31 12 views
5

Próbuję zaimplementować niestandardową logikę uwierzytelniania z najnowszą wersją Spring Boot, Web i Security, ale mam problemy z niektórymi problemami. Próbowałem wielu rozwiązań w podobnych pytaniach/tutorialach bez powodzenia lub zrozumienia, co faktycznie się dzieje.Wiosenny niestandardowy filtr uwierzytelniania i dostawca nie wywołujący metody sterownika

Tworzę aplikację REST z uwierzytelnieniem bezstanowym, tzn. Istnieje punkt końcowy REST (/ web/auth/login), który oczekuje nazwy użytkownika i hasła i zwraca token ciąg znaków, który jest następnie używany we wszystkich innych punktach końcowych REST (/ api/**) w celu identyfikacji użytkownika. Muszę zaimplementować niestandardowe rozwiązanie, ponieważ uwierzytelnianie stanie się bardziej złożone w przyszłości i chciałbym zrozumieć podstawy Spring Security.

Aby osiągnąć uwierzytelnianie tokena, tworzę niestandardowy filtr i dostawcy:

Filtr:

public class TokenAuthenticationFilter extends AbstractAuthenticationProcessingFilter { 

public TokenAuthenticationFilter() { 
    super(new AntPathRequestMatcher("/api/**", "GET")); 
} 

@Override 
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { 
    String token = request.getParameter("token"); 
    if (token == null || token.length() == 0) { 
     throw new BadCredentialsException("Missing token"); 
    } 

    UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(token, null); 

    return getAuthenticationManager().authenticate(authenticationToken); 
} 
} 

Dostawca:

@Component 
public class TokenAuthenticationProvider implements AuthenticationProvider { 
@Autowired 
private AuthenticationTokenManager tokenManager; 

@Override 
public Authentication authenticate(Authentication authentication) throws AuthenticationException { 
    String token = (String)authentication.getPrincipal(); 
    return tokenManager.getAuthenticationByToken(token); 
} 

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

config:

@EnableWebSecurity 
@Order(1) 
public class TokenAuthenticationSecurityConfig extends WebSecurityConfigurerAdapter { 
@Autowired 
private TokenAuthenticationProvider authProvider; 

@Override 
protected void configure(HttpSecurity http) throws Exception { 
    http.antMatcher("/api/**") 
    .csrf().disable() 
    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
    .and().addFilterBefore(authenticationFilter(), BasicAuthenticationFilter.class); 
} 

@Bean 
public TokenAuthenticationFilter authenticationFilter() throws Exception { 
    TokenAuthenticationFilter tokenProcessingFilter = new TokenAuthenticationFilter(); 
    tokenProcessingFilter.setAuthenticationManager(authenticationManager()); 
    return tokenProcessingFilter; 
} 

@Override 
public void configure(AuthenticationManagerBuilder auth) throws Exception { 
    auth.authenticationProvider(authProvider); 
} 
} 

AuthenticationTokenManager stosowany w operatora (a także w procesie logowania):

@Component 
public class AuthenticationTokenManager { 
private Map<String, AuthenticationToken> tokens; 

public AuthenticationTokenManager() { 
    tokens = new HashMap<>(); 
} 

private String generateToken(AuthenticationToken authentication) { 
    return UUID.randomUUID().toString(); 
} 

public String addAuthentication(AuthenticationToken authentication) { 
    String token = generateToken(authentication); 
    tokens.put(token, authentication); 
    return token; 
} 

public AuthenticationToken getAuthenticationByToken(String token) { 
    return tokens.get(token); 
} 

}

Co się dzieje: Jestem dołączając poprawny wyraz w żądaniu „/ api/bla "(który jest kontrolerem REST zwracającym część Json). Filtr i dostawca zostają wywołane. Problem jest następujący:, przeglądarka jest przekierowywana do "/" zamiast wywoływania żądanej metody kontrolera REST. Wydaje się, że dzieje się to w narzędziu SavedRequestAwareAuthenticationSuccessHandler, ale dlaczego używa się tego programu obsługi?

Próbowałem

  • wdrożyć pusty sukces obsługi, w wyniku kodu 200 stanu i nadal nie powołując kontroler
  • zrobić uwierzytelniania w prosty GenericFilterBean i ustawienie obiektu uwierzytelniania poprzez SecurityContextHolder .getContext(). setAuthentication (authentication), które skutkuje stroną błędu "Bad credentials".

Chciałbym zrozumieć, dlaczego mój kontroler nie jest wywoływana po uwierzytelnieniu tokena. Poza tym, czy istnieje "wiosenny" sposób przechowywania tokena, zamiast przechowywania go w mapie, jak niestandardowa implementacja SecurityContextRepository?

Naprawdę doceniam każdą podpowiedź!

+1

Jakieś działające rozwiązanie dla tego? Mamy ten sam problem i każda wskazówka lub działający kod byłby miły. – tg44

Odpowiedz

0

Może być trochę późno, ale miałem ten sam problem i dodając:

@Override 
protected void successfulAuthentication(
     final HttpServletRequest request, final HttpServletResponse response, 
     final FilterChain chain, final Authentication authResult) 
     throws IOException, ServletException { 
    chain.doFilter(request, response); 
} 

do mojego realizacji AbstractAuthenticationProcessingFilter załatwiło sprawę.

Powiązane problemy