Bereitstellen statischer Webressourcen in der Spring Boot & Spring Security-Anwendung

74

Ich versuche, die Spring Boot-Webanwendung zu entwickeln und mithilfe der Spring Security Java-Konfiguration zu sichern.

Nachdem ich meine statischen Webressourcen in ' src / main / resources / public ' platziert habe, wie hier im Spring-Blog empfohlen , kann ich die statischen Ressourcen abrufen. Wenn Sie also https://localhost/test.htmlim Browser klicken, wird der HTML-Inhalt bereitgestellt.

Problem

Nachdem ich Spring Security aktiviert habe, muss die statische Ressourcen-URL authentifiziert werden.

Meine relevante Spring Security Java-Konfiguration sieht folgendermaßen aus:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http.
            authorizeRequests()
                .antMatchers("/","/public/**", "/resources/**","/resources/public/**")
                    .permitAll()
                .antMatchers("/google_oauth2_login").anonymous()
                    .anyRequest().authenticated()
                .and()
                .formLogin()
                    .loginPage("/")
                    .loginProcessingUrl("/login")
                    .defaultSuccessUrl("/home")
                    .and()
                    .csrf().disable()
                    .logout()
                        .logoutSuccessUrl("/")
                        .logoutUrl("/logout") // POST only
                .and()
                    .requiresChannel()
                    .anyRequest().requiresSecure()
                .and()
                    .addFilterAfter(oAuth2ClientContextFilter(),ExceptionTranslationFilter.class)
                    .addFilterAfter(googleOAuth2Filter(),OAuth2ClientContextFilter.class)
                .userDetailsService(userService);
        // @formatter:on
    }

Wie sollte ich antMatchers so konfigurieren , dass statische Ressourcen in src / main / resources / public gespeichert werden ?

Kumar Sambhav
quelle
Siehe auch stackoverflow.com/questions/24164014/…
Samuli Pahaoja

Antworten:

103

Es gibt einige Dinge zu beachten:

  • Die Ant-Matcher stimmen mit dem Anforderungspfad und nicht mit dem Pfad der Ressource im Dateisystem überein.
  • Die eingegebenen Ressourcen src/main/resources/publicwerden vom Stammverzeichnis Ihrer Anwendung aus bereitgestellt. Zum Beispiel src/main/resources/public/hello.jpgwürde von serviert werdenhttp://localhost:8080/hello.jpg

Aus diesem Grund hat Ihre aktuelle Matcher-Konfiguration keinen Zugriff auf die statischen Ressourcen gewährt. Um /resources/**zu arbeiten, müssten Sie die Ressourcen in platzieren src/main/resources/public/resourcesund auf sie zugreifen http://localhost:8080/resources/your-resource.

Wenn Sie Spring Boot verwenden, sollten Sie die Standardeinstellungen verwenden, anstatt zusätzliche Konfigurationen hinzuzufügen. Frühlings - Boot wird standardmäßig erlaubt den Zugriff auf /css/**, /js/**, /images/**, und /**/favicon.ico. Sie könnten beispielsweise eine Datei mit dem Namen haben src/main/resources/public/images/hello.jpgund ohne zusätzliche Konfiguration darauf zugreifen, http://localhost:8080/images/hello.jpgohne sich anmelden zu müssen. Sie können dies in Aktion im Sicherheitsbeispiel für die Webmethode sehen, in dem der Zugriff auf die Bootstrap-CSS-Datei zulässig ist ohne spezielle Konfiguration.

Andy Wilkinson
quelle
1
- Ich habe das Spring Boot Sample Repo geklont und das Beispiel ausgeführt (Web Method Security Sample). Es funktioniert nicht. localhost: 8080 / css / bootstrap.min.css wird zur Anmeldeseite umgeleitet. - Es ist anders implementiert als beschriebene Lösung. Statische Datei hat Pfad: src / main / resources / static / css /
Florin Grozea
1
Siehe die Antwort von Thomas Lang, wenn Sie Spring Boot 2
Wim Deblauwe
static oder css js sollten sich in src / main / resources / public befinden. Hier ist der öffentliche Ordner der Schlüssel. Vielen Dank
Asifaftab87
Ich denke, dies wird benötigt http.authorizeRequests (). antMatchers ("/ css / **"). allowAll ()
Maayan Hope
Ich habe es verwendet web.ignoring().antMatchers("/static/**");, um Zugriff auf statische Ressourcen zu erhalten, aber jetzt leitet mich Spring Security immer wieder zu CSS um und zeigt nach der Anmeldung eine 404-Seite an, nicht zur Startseite. Die Homepage wird erst nach einer Aktualisierung angezeigt. Ich verwende nicht Spring Boot, sondern nur Spring MVC und Spring Security mit der Annotation @EnableWebSecurity, um es zu aktivieren.
Spalla Diego
30
  @Override
      public void configure(WebSecurity web) throws Exception {
        web
          .ignoring()
             .antMatchers("/resources/**"); // #3
      }

Ignorieren Sie alle Anforderungen, die mit "/ resources /" beginnen. Dies ähnelt der Konfiguration von http @ security = none bei Verwendung der XML-Namespace-Konfiguration.

RPaul
quelle
1
Funktioniert auch bei mir nicht. Während ich mein statisches HTML von einer API lade, verweise ich auf eine meiner statischen Dateien unter /resources/css/main.css. Die von der Rest-API gerenderte HTML-Seite funktioniert einwandfrei. Statisches CSS jedoch nicht.
Ranger Way
25

Dies kann gleichzeitig eine Antwort (für Spring Boot 2) und eine Frage sein. Es scheint, dass in Spring Boot 2 in Kombination mit Spring Security alles (dh jede Route / Antmatcher) standardmäßig geschützt ist, wenn Sie einen einzelnen Sicherheitsmechanismus verwenden, der von erweitert ist

WebSecurityConfigurerAdapter

Wenn Sie keinen individuellen Sicherheitsmechanismus verwenden, ist alles so wie es war?

In älteren Spring Boot-Versionen (1.5 und niedriger), wie Andy Wilkinson in seinen obigen Antwortstellen angibt, sind Orte wie public/** or static/**standardmäßig zulässig.

Um diese Frage / Antwort zusammenzufassen: Wenn Sie Spring Boot 2 mit Federsicherheit verwenden und über einen individuellen Sicherheitsmechanismus verfügen, müssen Sie ausschließlich den Zugriff auf statische Inhalte auf jeder Route zulassen. Wie so:

@Configuration
public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {

private final ThdAuthenticationProvider thdAuthenticationProvider;

private final ThdAuthenticationDetails thdAuthenticationDetails;

/**
 * Overloaded constructor.
 * Builds up the needed dependencies.
 *
 * @param thdAuthenticationProvider a given authentication provider
 * @param thdAuthenticationDetails  given authentication details
 */
@Autowired
public SpringSecurityConfiguration(@NonNull ThdAuthenticationProvider thdAuthenticationProvider,
                                   @NonNull ThdAuthenticationDetails thdAuthenticationDetails) {
    this.thdAuthenticationProvider = thdAuthenticationProvider;
    this.thdAuthenticationDetails = thdAuthenticationDetails;
}

/**
 * Creates the AuthenticationManager with the given values.
 *
 * @param auth the AuthenticationManagerBuilder
 */
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {

    auth.authenticationProvider(thdAuthenticationProvider);
}

/**
 * Configures the http Security.
 *
 * @param http HttpSecurity
 * @throws Exception a given exception
 */
@Override
protected void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests()
            .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
            .antMatchers("/management/**").hasAnyAuthority(Role.Role_Engineer.getValue(),
            Role.Role_Admin.getValue())
            .antMatchers("/settings/**").hasAnyAuthority(Role.Role_Engineer.getValue(),
            Role.Role_Admin.getValue())

            .anyRequest()
            .fullyAuthenticated()
            .and()
            .formLogin()
            .authenticationDetailsSource(thdAuthenticationDetails)
            .loginPage("/login").permitAll()
            .defaultSuccessUrl("/bundle/index", true)
            .failureUrl("/denied")
            .and()
            .logout()
            .invalidateHttpSession(true)
            .logoutSuccessUrl("/login")
            .logoutUrl("/logout")
            .and()
            .exceptionHandling()
            .accessDeniedHandler(new CustomAccessDeniedHandler());
}

}}

Bitte beachten Sie diese Codezeile, die neu ist:

.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()

Wenn Sie Spring Boot 1.5 und niedriger verwenden, müssen Sie diese Speicherorte (statisch / öffentlich / Webjars usw.) nicht explizit zulassen.

Hier ist der offizielle Hinweis, was sich im neuen Sicherheitsrahmen gegenüber alten Versionen von sich selbst geändert hat:

Sicherheitsänderungen in Spring Boot 2.0 M4

Ich hoffe das hilft jemandem. Vielen Dank! Einen schönen Tag noch!

Thomas Lang
quelle
2
Ich kann bestätigen, dass das Hinzufügen der zusätzlichen Zeile das
Problem
1
Zusätzliche Zeile hilft viel, aber ich muss noch ein paar Zeilen hinzufügen, damit es funktioniert. Boot-Version 2.0.6. (1) .antMatchers ("/", "/ callback", "/ login **", "/ webjars / **", "/ error **", "/ static / **"). PermitAll () und (2) registry.addResourceHandler ("/ static / **"). AddResourceLocations ("classpath: / static /"); unter WebMvcConfigurer.addResourceHandlers ().
Riten
Vielen Dank dafür!
Jazerix
22

Hier ist die ultimative Lösung nach mehr als 20 Stunden Recherche.

Schritt 1. Fügen Sie Ihrem Projekt 'MvcConfig.java' hinzu.

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry
                .addResourceHandler("/resources/**")
                .addResourceLocations("/resources/");
    }
}

Schritt 2. Fügen Sie configure(WebSecurity web)Ihrer SecurityConfig-Klasse eine Überschreibung hinzu

@Override
    public void configure(WebSecurity web) throws Exception {
        web
                .ignoring()
                .antMatchers("/resources/**");
    }

Schritt 3. Platzieren Sie alle statischen Ressourcen in webapp / resources / ..

JasperJ
quelle
1
Können Sie erklären, was Sie tun und warum? "Schritt 1": Statische Ressourcenbehandlung hinzufügen. "Schritt 2": Statische Ressourcenbehandlung entfernen.
Loshad Vtapkah
Wenn jemand eine XML-Konfiguration verwendet, können Sie in Schritt 1 diese Zeile <mvc:resources mapping="/resources/**" location="/resources/" />in Ihrer verwenden, dispatcher-servlet.xmlanstatt eine neue Java-Konfigurationsklasse zu erstellen.
GDRT
9

Wenn Sie Webjars verwenden. Sie müssen dies in Ihrer configureMethode hinzufügen : http.authorizeRequests().antMatchers("/webjars/**").permitAll();

Stellen Sie sicher, dass dies die erste Aussage ist. Zum Beispiel:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/webjars/**").permitAll();
        http.authorizeRequests().anyRequest().authenticated();
         http.formLogin()
         .loginPage("/login")
         .failureUrl("/login?error")
         .usernameParameter("email")
         .permitAll()
         .and()
         .logout()
         .logoutUrl("/logout")
         .deleteCookies("remember-me")
         .logoutSuccessUrl("/")
         .permitAll()
         .and()
         .rememberMe();
    }

Sie benötigen dies auch, um Webjars zu aktivieren:

@Configuration
    public class MvcConfig extends WebMvcConfigurerAdapter {
        ...
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
                registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
        }
        ...
    }
ACV
quelle
5
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        String[] resources = new String[]{
                "/", "/home","/pictureCheckCode","/include/**",
                "/css/**","/icons/**","/images/**","/js/**","/layer/**"
        };

        http.authorizeRequests()
                .antMatchers(resources).permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout().logoutUrl("/404")
                .permitAll();
        super.configure(http);
    }
}
Huangxu Huang
quelle
Wird der Aufruf super.configureBasic Auth nicht aktivieren?
Peterchaula
1

Ich hatte das gleiche Problem mit meiner Spring Boot-Anwendung, also dachte ich, es wäre schön, wenn ich euch meine Lösung mitteilen würde. Ich konfiguriere die antMatchers einfach so , dass sie für bestimmte Arten von Füllungen geeignet sind. In meinem Fall war das nur js filles und js.map . Hier ist ein Code:

   @Configuration
   @EnableWebSecurity
   public class SecurityConfig extends WebSecurityConfigurerAdapter {

   @Override
   protected void configure(HttpSecurity http) throws Exception {
       http.authorizeRequests()
      .antMatchers("/index.html", "/", "/home", 
       "/login","/favicon.ico","/*.js","/*.js.map").permitAll()
      .anyRequest().authenticated().and().csrf().disable();
   }
  }

Was ist interessant. Ich finde heraus, dass der Ressourcenpfad wie "resources / myStyle.css" in antMatcher für mich überhaupt nicht funktioniert hat. Wenn Sie einen Ordner in Ihrem Resoruces-Ordner haben, fügen Sie ihn einfach in antMatcher wie "/myFolder/myFille.js"*" hinzu und es sollte einwandfrei funktionieren.

Ziumper
quelle
Für diejenigen, die die meisten Ressourcen benötigen: http.authorizeRequests (). AntMatchers (HttpMethod.GET, "/", "/index.html", "/favicon.ico", "/**/*.js", "/ * * / *. js.map "," /**/*.css "," /assets/images/*.png "," /assets/images/*.jpg "," /assets/images/*.jpeg " "," /assets/images/*.gif "," /**/*.ttf "," /**/*.json "," /**/*.woff "," / ** / *. woff2 "," /**/*.eot "," / ** / *. svg "). allowAll () Wenn Sie sich fragen, warum double **. Mit ** bedeutet dies, dass überall dort zugelassen wird, wo sich eine Datei mit dieser Erweiterung befindet. Beachten Sie auch die Datei HTTPMETHOD.GET. Ersetzen Sie / Assets / Images durch Ihren eigenen Ordner. Ansonsten setzen Sie einfach /*.jpg
Merv