Wie sichere ich die REST-API mit Spring Boot und Spring Security?


80

Ich weiß, dass das Sichern der REST-API ein häufig kommentiertes Thema ist, aber ich kann keinen kleinen Prototyp erstellen, der meinen Kriterien entspricht (und ich muss bestätigen, dass diese Kriterien realistisch sind). Es gibt so viele Möglichkeiten, Ressourcen zu sichern und mit Spring Security zu arbeiten, dass ich klären muss, ob meine Anforderungen realistisch sind.

Meine Anforderungen

  • Token-basierter Authentifikator - Benutzer geben ihre Anmeldeinformationen ein und erhalten ein eindeutiges und zeitlich begrenztes Zugriffstoken. Ich möchte die Tokenerstellung verwalten, die Gültigkeit und den Ablauf in meiner eigenen Implementierung überprüfen.
  • Einige REST-Ressourcen sind öffentlich - Sie müssen sich überhaupt nicht authentifizieren.
  • Einige Ressourcen sind nur für Benutzer mit Administratorrechten zugänglich.
  • Andere Ressourcen sind nach der Autorisierung für alle Benutzer verfügbar.
  • Ich möchte die Standardauthentifizierung nicht verwenden
  • Java-Code-Konfiguration (nicht XML)

Aktueller Status

Meine REST-API funktioniert sehr gut, aber jetzt muss ich sie sichern. Als ich nach einer Lösung suchte, habe ich einen javax.servlet.FilterFilter erstellt:

  @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;

        String accessToken = request.getHeader(AUTHORIZATION_TOKEN);
        Account account = accountDao.find(accessToken);

        if (account == null) {    
            throw new UnauthorizedException();    
        }

        chain.doFilter(req, res);

    }

Diese Lösung mit javax.servlet.filtersfunktioniert jedoch nicht so, wie ich es brauche, da es ein Problem mit der Ausnahmebehandlung über @ControllerAdviceSpring gibt servlet dispatcher.

Was ich brauche

Ich würde gerne wissen, ob diese Kriterien realistisch sind und Hilfe erhalten, wie Sie mit der Sicherung der REST-API mit Spring Security beginnen können. Ich habe viele Tutorials gelesen (z. B. Spring Data REST + Spring Security ), aber alle funktionieren in einer sehr einfachen Konfiguration - Benutzer mit ihren Anmeldeinformationen werden in der Konfiguration im Speicher gespeichert, und ich muss mit DBMS arbeiten und einen eigenen Authentifikator erstellen.

Bitte geben Sie mir einige Ideen, wie ich anfangen soll.

Antworten:


67

Token-basierte Authentifizierung - Benutzer geben ihre Anmeldeinformationen ein und erhalten ein eindeutiges und zeitlich begrenztes Zugriffstoken. Ich möchte die Tokenerstellung verwalten, die Gültigkeit und den Ablauf in meiner eigenen Implementierung überprüfen.

Verwenden Sie Filter für Token-Authentifizierung - in diesem Fall am besten

Schließlich können Sie CRUD über Spring Data erstellen, um die Eigenschaften von Token zu verwalten, die ablaufen usw.

Hier ist mein Token-Filter: http://pastebin.com/13WWpLq2

Und Token Service Implementierung

http://pastebin.com/dUYM555E

Einige REST-Ressourcen sind öffentlich - eine Authentifizierung ist überhaupt nicht erforderlich

Es ist kein Problem, Sie können Ihre Ressourcen über die Spring-Sicherheitskonfiguration wie folgt verwalten: .antMatchers("/rest/blabla/**").permitAll()

Einige Ressourcen sind nur für Benutzer mit Administratorrechten zugänglich.

Schauen Sie sich die @SecuredAnmerkungen zum Unterricht an. Beispiel:

@Controller
@RequestMapping(value = "/adminservice")
@Secured("ROLE_ADMIN")
public class AdminServiceController {

Die andere Ressource ist nach der Autorisierung für alle Benutzer zugänglich.

Zurück zur Konfiguration von Spring Security können Sie Ihre URL folgendermaßen konfigurieren:

    http
            .authorizeRequests()
            .antMatchers("/openforall/**").permitAll()
            .antMatchers("/alsoopen/**").permitAll()
            .anyRequest().authenticated()

Ich möchte die Standardauthentifizierung nicht verwenden

Ja, über den Token-Filter werden Ihre Benutzer authentifiziert.

Java-Code-Konfiguration (nicht XML)

Zurück zu den obigen Worten @EnableWebSecurity. Ihre Klasse wird sein:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {}

Sie müssen die Konfigurationsmethode überschreiben . Code unten, nur zum Beispiel, wie Matcher konfiguriert werden. Es ist aus einem anderen Projekt.

    @Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers("/assets/**").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
                .usernameParameter("j_username")
                .passwordParameter("j_password")
                .loginPage("/login")
                .defaultSuccessUrl("/", true)
                .successHandler(customAuthenticationSuccessHandler)
                .permitAll()
            .and()
                .logout()
                .logoutUrl("/logout")
                .invalidateHttpSession(true)
                .logoutSuccessUrl("/")
                .deleteCookies("JSESSIONID")
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
            .and()
                .csrf();
}

Kannst du mir bitte bei meiner Frage helfen? stackoverflow.com/questions/46065063/…
Felipe A.

2
Gibt es ein Beispielprojekt, das alle Anforderungen enthält?
AlikElzin-Kilaka

@Oleksandr: Das ist ein langer Weg, aber können Sie mir sagen, warum Sie einen Thread in der updateLastLogin (...) -Methode der RESTAuthenticationTokenProcessingFilter-Klasse gestartet haben?
Z3d4s

1
@ z3d4s, eigentlich ist es ein altes Beispiel (4 Jahre), für den Moment werde ich vorschlagen, OffsetDateTime, andere Ansätze usw. zu verwenden :) neuer Thread, den ich vorgeschlagen habe, um die Verarbeitungszeit für Benutzeranforderungen zu verkürzen, da es beim Speichern zusätzliche Zeit dauern kann in die Datenbank.
Oleksandr Loushkin

Ahhh ich verstehe, das ist eine geniale Lösung! Vielen Dank!
Z3d4s

4

Spring Security ist auch sehr nützlich, um die REST-URLs zu authentifizieren und zu autorisieren. Wir müssen keine benutzerdefinierten Implementierungen angeben.

Zunächst müssen Sie den Einstiegspunkt-ref für restAuthenticationEntryPoint in Ihrer Sicherheitskonfiguration wie folgt angeben.

 <security:http pattern="/api/**" entry-point-ref="restAuthenticationEntryPoint" use-expressions="true" auto-config="true" create-session="stateless" >

    <security:intercept-url pattern="/api/userList" access="hasRole('ROLE_USER')"/>
    <security:intercept-url pattern="/api/managerList" access="hasRole('ROLE_ADMIN')"/>
    <security:custom-filter ref="preAuthFilter" position="PRE_AUTH_FILTER"/>
</security:http>

Die Implementierung für den restAuthenticationEntryPoint könnte wie folgt aussehen.

 @Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {

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

Danach müssen Sie RequestHeaderAuthenticationFilter angeben. Es enthält den RequestHeader-Schlüssel. Dies wird im Wesentlichen zur Identifizierung der Benutzerauthentifizierung verwendet. Im Allgemeinen überträgt RequestHeader diese Informationen während der REST-Aufrufe. Betrachten Sie zum Beispiel den folgenden Code

   <bean id="preAuthFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
    <property name="principalRequestHeader" value="Authorization"/>
    <property name="authenticationManager" ref="authenticationManager" />
  </bean>

Hier,

<property name="principalRequestHeader" value="Authorization"/>

"Autorisierung" ist der Schlüssel für die eingehende Anfrage. Es enthält die erforderlichen Authentifizierungsinformationen des Benutzers. Außerdem müssen Sie den PreAuthenticatedAuthenticationProvider so konfigurieren, dass er unsere Anforderungen erfüllt.

   <bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService">
  <bean id="userDetailsServiceWrapper"
      class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
    <property name="userDetailsService" ref="authenticationService"/>
  </bean>
</property>
</bean>

Dieser Code dient zum Sichern der REST-URLs durch Authentifizierung und Autorisierung ohne benutzerdefinierte Implementierungen.

Den vollständigen Code finden Sie unter folgendem Link:

https://github.com/srinivas1918/spring-rest-security



-1

Um die REST-API zu validieren, gibt es zwei Möglichkeiten

1 - Grundlegende Authentifizierung unter Verwendung des in der Datei application.properties festgelegten Standardbenutzernamens und -kennworts

Grundlegende Authentifizierung

2 - Authentifizieren Sie sich mithilfe der Datenbank (userDetailsService) mit dem tatsächlichen Benutzernamen und Passwort

Erweiterte Authentifizierung


Video ist nützlich. So führen Sie dieselbe erweiterte Authentifizierung für die ReST-API durch. Hier nur über Web beschreiben. Gibt es ein Video-Tutorial für die erweiterte Authentifizierung in der REST-API?
Jacob

Wenn Sie das 2. Video (Erweiterte Authentifizierung) gesehen haben, mache ich die gleiche Authentifizierung auch mit dem REST-Client (für die REST-API).
Jeet Singh Parmar
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.