2014-03-12 26 views
5

Ich versuche, einen benutzerdefinierten Filter durchzuführen, um ein Token zu erhalten und es zu überprüfen. Ich folge dem Ansatz in dieser response.Spring Security benutzerdefinierte Token-Filter

Dies ist die entsprechende Konfiguration:

SecurityConfig:

@Configuration 
@EnableWebSecurity 
@ComponentScan(basePackages = {"com.company.app"}) 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

@Inject 
AuthenticationTokenFilter authenticationTokenFilter; 

@Inject 
TokenAuthenticationProvider tokenAuthenticationProvider; 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
      .addFilterBefore(authenticationTokenFilter, BasicAuthenticationFilter.class) 
       .antMatcher("/*") 
       .authenticationProvider(tokenAuthenticationProvider) 
       .authorizeRequests() 
        .anyRequest().authenticated(); 
    } 

} 

AuthenticationTokenFilter:

@Component 
public class AuthenticationTokenFilter implements Filter { 

private static final Logger logger = LoggerFactory.getLogger(AuthenticationTokenFilter.class); 

@Override 
public void init(FilterConfig fc) throws ServletException { 
    logger.info("Init AuthenticationTokenFilter"); 
} 

@Override 
public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc) throws IOException, ServletException { 
    SecurityContext context = SecurityContextHolder.getContext(); 
    if (context.getAuthentication() != null && context.getAuthentication().isAuthenticated()) { 
     // do nothing 
    } else { 
     Map<String,String[]> params = req.getParameterMap(); 
     if (!params.isEmpty() && params.containsKey("auth_token")) { 
      String token = params.get("auth_token")[0]; 
      if (token != null) { 
       Authentication auth = new TokenAuthentication(token); 
       SecurityContextHolder.getContext().setAuthentication(auth); 
      } 
     } 
    } 

    fc.doFilter(req, res); 
} 

@Override 
public void destroy() { 

} 
} 

TokenAuthentication:

public class TokenAuthentication implements Authentication { 
private String token; 

public TokenAuthentication(String token) { 
    this.token = token; 
} 
@Override 
public Collection<? extends GrantedAuthority> getAuthorities() { 
    return new ArrayList<GrantedAuthority>(0); 
} 
@Override 
public Object getCredentials() { 
    return token; 
} 
@Override 
public Object getDetails() { 
    return null; 
} 
@Override 
public Object getPrincipal() { 
    return null; 
} 
@Override 
public boolean isAuthenticated() { 
    return false; 
} 
@Override 
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { 
} 
@Override 
public String getName() { 
    return null; 
} 
} 

TokenAu thenticationProvider:

@Component 
public class TokenAuthenticationProvider implements AuthenticationProvider { 

private static final Logger logger = LoggerFactory.getLogger(TokenAuthenticationProvider.class); 

@Override 
public Authentication authenticate(Authentication auth) throws AuthenticationException { 
    if (auth.isAuthenticated()) 
     return auth; 

    String token = auth.getCredentials().toString(); 
    User user = userSvc.validateApiAuthenticationToken(token); 
    if (user != null) { 
     auth = new PreAuthenticatedAuthenticationToken(user, token); 
     auth.setAuthenticated(true); 
     logger.debug("Token authentication. Token: "); 
    } else 
     throw new BadCredentialsException("Invalid token " + token); 
    return auth; 
} 

@Override 
public boolean supports(Class<?> aClass) { 
    return true; 
} 

} 

Aber es ist wie der AuthenticationTokenFilter wird, nicht zu der Kette hinzugefügt. Debugging Ich kann sehen, dass wenn ich einen Anruf mache, es in die SecurityConfig und Configure-Methode eintritt, aber nicht auf den Filter. Was fehlt?

+0

haben Sie andere Sicherheitskonfigurations Klassen? –

+0

@Eugen Halca nein, fehlt etwas? – Federico

+0

es sieht aus wie es sollte funktionieren, ich hatte einige seltsame Verhaltensweisen wie Ihre, es war mit '@ Order' Annotation auf Sicherheit Konfig Klassen –

Antwort

3

versuchen, anonymous Authentifizierung zu deaktivieren und zu fully Authentifizierung zu Ihrer Sicherheitsregel ändern.

etwas wie folgt aus:

http 
    .addFilterBefore(authenticationTokenFilter, BasicAuthenticationFilter.class) 
        .antMatcher("/token") 
        .authenticationProvider(tokenAuthenticationProvider) 
        .authorizeUrls().anyRequest().fullyAuthenticated() 
    .and() 
        .anonymous().disable() 
+0

kann nicht Methode auflösen – Federico

+0

Sie sollten mindestens "Spring-Security-javaconfig-1.0.0.M1.jar", die kompilieren ist –

+0

Ich habe Feder-Sicherheit-Web-und Feder-Sicherheits-Config, warum ist das lib notwendig? – Federico

2

Was Ihnen fehlt, ist

<filter> 
     <filter-name>springSecurityFilterChain</filter-name> 
     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
</filter> 
<filter-mapping> 
     <filter-name>springSecurityFilterChain</filter-name> 
     <url-pattern>/*</url-pattern> 
</filter-mapping> 

in Ihrem web.xml oder gleichwertig für Initialisierer auf Ihrem Classpath:

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; 

@Order(value = 1) 
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer { 
} 

Dies ist unabhängig von Ihrem WebApplicationInitializer. Beachten Sie, dass:

  • Ihre SecurityConfig (oder irgendetwas mit @EnableWebSecurity kommentierten) müssen im Root-Kontext definiert werden (nicht der Disponent Kontext)
  • Sie wahrscheinlich order of initialization verstehen sollte (ich bin nicht sicher, ob ich):

"Bestellen von WebApplicationInitializer"
Wenn ein Servlet-Filter-Zuordnungen hinzugefügt werden, nachdem AbstractSecurityWebApplicationInitializer aufgerufen wird, könnten sie versehentlich vor springSecurityFilterChain hinzugefügt werden. Sofern eine Anwendung keine Filterinstanzen enthält, die nicht gesichert werden müssen, sollte springSecurityFilterChain vor allen anderen Filterzuordnungen stehen. Mit der @Order-Annotation kann sichergestellt werden, dass WebApplicationInitializer in einer deterministischen Reihenfolge geladen wird.

Beispiel:

@Order(value = 10) 
public class AppWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { 

    @Override 
    protected Class<?>[] getRootConfigClasses() { 
     return new Class<?>[] { AppConfig.class, SecurityConfig.class }; 
    } 

    @Override 
    protected Class<?>[] getServletConfigClasses() { 
     return new Class<?>[] { RestConfig.class }; 
    } 

    @Override 
    protected String[] getServletMappings() { 
     return new String[] { "/rest/*"}; 
    } 
} 


Zusammengefasst aus Spring Dokumentation:

Wenn Servlet-Filter verwenden, können Sie natürlich sie in Ihrem web.xml erklären müssen, oder sie werden ignoriert vom Servlet-Container.In Spring Security sind die Filterklassen auch Spring-Beans, die im Anwendungskontext definiert sind, und können daher die umfangreichen Abhängigkeitsinjektionsfunktionen und Lebenszyklusschnittstellen von Spring nutzen. DelegatingFilterProxy von Spring stellt die Verbindung zwischen web.xml und dem Anwendungskontext her.

The Security Filter Chain

0

Alte Post, aber ich denke, authenticationProvider() vor "addBeforeFilter" kommen muss. Ich bin mir nicht sicher, ob es heute einen Unterschied machen wird, aber es könnte wichtig sein. Es ist vielleicht nicht so wichtig.

versuchen auch diese Klasse auf Ihrer Konfiguration hinzuzufügen, um das Problem zu lösen:

@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 
Verwandte Themen