在Spring Boot和Spring Security应用程序中提供静态Web资源


75

我正在尝试开发Spring Boot Web应用程序并使用Spring Security Java配置对其进行保护。

按照Spring博客中的建议,将我的静态Web资源放置在“ src / main / resources / public中后,便可以获取静态资源。即https://localhost/test.html在浏览器中点击确实提供html内容。

问题

在启用Spring Security之后,访问静态资源URL需要身份验证。

我的相关事件Spring Security Java配置看起来像这样:-

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

我应该如何配置antMatchers以允许将静态资源放置在src / main / resources / public中?


Answers:


104

有几件事要注意:

  • Ant匹配器将根据请求路径而不是文件系统上资源的路径进行匹配。
  • 放置的资源src/main/resources/public将从您的应用程序的根目录开始。例如src/main/resources/public/hello.jpg将从http://localhost:8080/hello.jpg

这就是为什么您当前的匹配器配置不允许访问静态资源的原因。为了/resources/**工作,您必须将资源放入src/main/resources/public/resources并在处进行访问http://localhost:8080/resources/your-resource

使用Spring Boot时,您可能需要考虑使用其默认值,而不是添加额外的配置。春天开机就会在默认情况下,允许访问/css/**/js/**/images/**,和/**/favicon.ico。例如,您可以拥有一个名为的文件src/main/resources/public/images/hello.jpg,而无需添加任何额外的配置,http://localhost:8080/images/hello.jpg无需登录即可访问该文件。您可以在允许对Bootstrap CSS进行访问的Web方法安全性冒烟测试中看到此操作文件没有任何特殊配置。


1
-我已经克隆了Spring Boot示例存储库并运行了示例(Web方法安全示例)。它不起作用。localhost:8080 / css / bootstrap.min.css重定向到登录页面。-与描述的解决方案不同。静态文件的路径为:src / main / resources / static / css /
Florin Grozea

1
如果您使用的是Spring Boot 2,请查看Thomas Lang的答案
Wim Deblauwe,

静态或css js应该位于src / main / resources / public内,其中公共文件夹是关键。谢谢
asifaftab87 '19

我认为这是必需的http.authorizeRequests()。antMatchers(“ / css / **”)。permitAll()
Maayan Hope

我曾经使用web.ignoring().antMatchers("/static/**");过以获得静态资源的访问权限,但现在Spring Security始终将我重定向到CSS并在登录后显示404页面,而不是首页。仅在刷新后才显示主页。我没有使用spring boot,而是仅使用spring MVC和带有@EnableWebSecurity批注的spring安全性来激活它。
Spalla Diego

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

忽略任何以“ / resources /”开头的请求。这与使用XML名称空间配置时配置http @ security = none相似。


1
也不适合我。当我从API加载静态html时,请在/resources/css/main.css中引用我的一个静态文件。Rest API呈现的html页面工作正常。但是,静态CSS没有。
游侠之路

25

这可能是一个答案(对于弹簧靴2),同时是一个问题。似乎在Spring Boot 2与Spring Security结合使用时,如果您使用从

WebSecurityConfigurerAdapter

如果您不使用单独的安全机制,那么一切都照原样了吗?

在较早的春季靴子版本(1.5及更低版本)中,如Andy Wilkinson在上面的答案中所述, public/** or static/**,默认情况下允许位置。

因此,总而言之,如果您使用的是具有弹簧安全性的Spring Boot 2,并且具有单独的安全性机制,则必须排除允许访问放置在任何路径上的静态内容的可能性。像这样:

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

}

请注意这行代码是新的:

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

如果您使用的是Spring Boot 1.5及更低版本,则无需明确允许这些位置(静态/公共/ webjars等)。

这是官方说明,新的安全框架相对于旧版本本身发生了什么变化:

Spring Boot 2.0 M4中的安全性更改

我希望这可以帮助别人。谢谢!祝你今天愉快!


2
我可以确认,添加额外的行对我来说已经解决了(Spring Boot 2.0.3)
Wim Deblauwe

1
额外的行确实有很大帮助,但是我需要添加几行以使其正常运行。引导版本2.0.6。(1).antMatchers(“ /”,“ / callback”,“ / login **”,“ / webjars / **”,“ / error **”,“ / static / **”)。permitAll()和(2)Registry.addResourceHandler(“ / static / **”)。addResourceLocations(“ classpath:/ static /”); 在WebMvcConfigurer.addResourceHandlers()下。
仪式

非常感谢你做的这些!
Jazerix

22

经过20多个小时的研究,这是最终的解决方案。

步骤1.将“ MvcConfig.java”添加到您的项目。

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

步骤2.configure(WebSecurity web)覆盖添加到SecurityConfig类

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

步骤3.将所有静态资源放在webapp / resources /中。


2
您能解释一下您在做什么,为什么吗?“ Step1”:添加静态资源处理。“ Step2”:删除静态资源处理。
洛沙德vtapkah,2016年

1
如果有人使用XML配置,则可以在步骤1中使用此行<mvc:resources mapping="/resources/**" location="/resources/" />dispatcher-servlet.xml而不用创建新的Java配置类。
gdrt

9

如果您使用的是webjars。您需要在您的configure方法中: http.authorizeRequests().antMatchers("/webjars/**").permitAll();

确保这是第一条声明。例如:

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

您还需要具有此功能才能启用webjar:

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

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

通话会super.configure不会启用基本身份验证?
peterchaula

1

我的Spring Boot应用程序也遇到了同样的问题,所以我想如果我能与大家分享我的解决方案,那就太好了。我只是简单地将antMatchers配置为适合特定类型的填充。就我而言,只有js filles和js.map。这是一个代码:

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

有趣的是。我发现antMatcher中的资源路径(“ resources / myStyle.css”)根本不适合我。如果您在resoruces文件夹中有该文件夹,只需将其添加到antMatcher中,例如“ /myFolder/myFille.js”*,即可正常工作。


对于那些需要最多资源的用户: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“)。permitAll()如果您想知道为什么加倍**。使用**表示允许在任何带有该扩展名的文件的地方进行许可。还要注意HTTPMETHOD.GET。用您自己的文件夹替换/ assets / images。否则就放/*.jpg
Merv
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.