2016-07-31 21 views
5

Ich versuche, eine benutzerdefinierte Authentifizierungslogik mit der neuesten Version von Spring Boot, Web und Sicherheit zu implementieren, aber ich habe mit einigen Problemen zu kämpfen. Ich habe viele Lösungen in ähnlichen Fragen/Tutorials ohne Erfolg ausprobiert oder verstanden, was tatsächlich passiert.Benutzerdefinierte Authentifizierungsfilter für Spring und Provider, die Controller-Methode nicht aufrufen

Ich erstelle eine REST-Anwendung mit zustandsloser Authentifizierung, dh es gibt einen REST-Endpunkt (/ web/auth/login), der Benutzernamen und Passwort erwartet und ein String-Token zurückgibt, das dann in allen anderen REST-Endpunkten verwendet wird (/ api/**) um den Benutzer zu identifizieren. Ich muss eine benutzerdefinierte Lösung implementieren, da die Authentifizierung in Zukunft komplexer wird und ich die Grundlagen von Spring Security verstehen möchte.

die Token-Authentifizierung Um das zu erreichen, ich bin ein individuelles Filter und Anbieter zu schaffen:

Der Filter:

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); 
} 
} 

Der Anbieter:

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

Die 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); 
} 
} 

Die AuthenticationTokenManager im Provider verwendet (und auch in der Login-Prozess):

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

}

Was passiert: Ich bin in der Anfrage ein gültiges Token Anhängen an „/ api/bla "(Dies ist ein REST-Controller, der einige Json zurückgibt). Der Filter und der Provider werden beide aufgerufen. Das Problem ist, der Browser wird auf "/" umgeleitet, anstatt die angeforderte Methode des REST-Controllers aufzurufen. Dies scheint in SavedRequestAwareAuthenticationSuccessHandler zu passieren, aber warum wird dieser Handler verwendet?

Ich versuchte

  • einen leeren Erfolg Handler zu implementieren, in einem 200-Statuscode, und immer noch nicht das Aufrufen der Controller
  • Authentifizierung in einem einfachen GenericFilterBean zu tun und die Einstellung der Authentifikationsobjekt über SecurityContextHolder .getContext(). setAuthentication (Authentifizierung), die zu einer Fehlerseite "Bad credentials" führt.

Ich möchte verstehen, warum mein Controller nicht aufgerufen wird, nachdem ich das Token authentifiziert habe. Gibt es außerdem eine "Spring" -Möglichkeit, das Token zu speichern, anstatt es in einer Map zu speichern, wie bei einer benutzerdefinierten Implementierung von SecurityContextRepository?

Ich schätze wirklich jeden Hinweis!

+1

Irgendeine funktionierende Lösung dafür? Wir haben das gleiche Problem und jeder Hinweis oder Arbeitscode wäre nett. – tg44

Antwort

0

vielleicht ein wenig spät, aber ich war das gleiche Problem und fügt hinzu:

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

meiner AbstractAuthenticationProcessingFilter Implementierung hat den Trick.