Spring Security - Token basierte API Auth & amp; Benutzer / Passwort-Authentifizierung

Ich versuche zum erstellen einer webapp wird in Erster Linie bieten eine REST-API mithilfe der Frühling, und bin versucht, konfigurieren Sie die security-Seite.

Ich versuche zu implementieren, die diese Art von Muster: https://developers.google.com/accounts/docs/MobileApps (Google verändert, dass die Seite so keinen Sinn mehr macht - siehe die Seite meinte ich hier: http://web.archive.org/web/20130822184827/https://developers.google.com/accounts/docs/MobileApps)

Hier ist, was ich brauche, um accompish:

  • Web-app hat einfache, sign-in/sign-up-Formulare, die die Arbeit mit normalen Frühling Benutzer/Kennwort-Authentifizierung (getan haben, diese Art der Sache vor mit dao/authenticationmanager/userdetailsservice etc)
  • REST api-Endpunkte, auf stateless sessions und jede Anforderung authentifiziert basierend ona-token zur Verfügung gestellt, mit der Aufforderung,

werden(z.B. Benutzer-logins/Zeichen mit den normalen Formen, die webapp bietet Sicheres cookie mit dem token, das verwendet werden kann in folgende API-Anfragen)

Ich hatte eine normale Authentifizierung setup wie folgt:

@Override protected void configure(HttpSecurity http) throws Exception {
    http
        .csrf()
            .disable()
        .authorizeRequests()
            .antMatchers("/resources/**").permitAll()
            .antMatchers("/mobile/app/sign-up").permitAll()
            .antMatchers("/v1/**").permitAll()
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .loginPage("/")
            .loginProcessingUrl("/loginprocess")
            .failureUrl("/?loginFailure=true")
            .permitAll();
}

Ich dachte an das hinzufügen eines pre-auth-filter, der überprüft, ob das token in der Anfrage und dann legt den Sicherheitskontext (würde das bedeuten, dass die normalen nach Authentifizierung übersprungen wird?), aber über die normale Benutzer/Passwort habe ich nicht allzu viel getan, mit token-basierte Sicherheit, aber basierend auf einige andere Beispiele, die ich kam mit die folgenden:

Security Config:

@Override protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf()
                .disable()
            .addFilter(restAuthenticationFilter())
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .exceptionHandling().authenticationEntryPoint(new Http403ForbiddenEntryPoint()).and()
                .antMatcher("/v1/**")
            .authorizeRequests()
                .antMatchers("/resources/**").permitAll()
                .antMatchers("/mobile/app/sign-up").permitAll()
                .antMatchers("/v1/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/")
                .loginProcessingUrl("/loginprocess")
                .failureUrl("/?loginFailure=true")
                .permitAll();
    }

Meine eigene rest-filter:

public class RestAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    public RestAuthenticationFilter(String defaultFilterProcessesUrl) {
        super(defaultFilterProcessesUrl);
    }

    private final String HEADER_SECURITY_TOKEN = "X-Token"; 
    private String token = "";


    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        this.token = request.getHeader(HEADER_SECURITY_TOKEN);

        //If we have already applied this filter - not sure how that would happen? - then just continue chain
        if (request.getAttribute(FILTER_APPLIED) != null) {
            chain.doFilter(request, response);
            return;
        }

        //Now mark request as completing this filter
        request.setAttribute(FILTER_APPLIED, Boolean.TRUE);

        //Attempt to authenticate
        Authentication authResult;
        authResult = attemptAuthentication(request, response);
        if (authResult == null) {
            unsuccessfulAuthentication(request, response, new LockedException("Forbidden"));
        } else {
            successfulAuthentication(request, response, chain, authResult);
        }
    }

    /**
     * Attempt to authenticate request - basically just pass over to another method to authenticate request headers 
     */
    @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        AbstractAuthenticationToken userAuthenticationToken = authUserByToken();
        if(userAuthenticationToken == null) throw new AuthenticationServiceException(MessageFormat.format("Error | {0}", "Bad Token"));
        return userAuthenticationToken;
    }


    /**
     * authenticate the user based on token, mobile app secret & user agent
     * @return
     */
    private AbstractAuthenticationToken authUserByToken() {
        AbstractAuthenticationToken authToken = null;
        try {
            //TODO - just return null - always fail auth just to test spring setup ok
            return null;
        } catch (Exception e) {
            logger.error("Authenticate user by token error: ", e);
        }
        return authToken;
    }

Oben führt tatsächlich zu einem Fehler bei app-Start zu sagen: authenticationManager must be specified
Kann mir jemand sagen, wie man am besten, dies zu tun - ist ein pre_auth filter der beste Weg, dies zu tun?


BEARBEITEN

Schrieb ich, was ich gefunden habe und wie ich es gemacht habe mit Spring-security (einschließlich code) Implementierung einer standard-token-Implementierung (nicht OAuth)

Überblick über die Problematik und die Herangehensweise/Lösung

Die Implementierung der Lösung mit Spring-security

Hoffe, es hilft einigen anderen.

InformationsquelleAutor der Frage rhinds | 2014-02-24

Schreibe einen Kommentar