【问题标题】:Serving static web resources in Spring Boot & Spring Security application在 Spring Boot 和 Spring Security 应用程序中提供静态 Web 资源
【发布时间】:2014-09-15 00:22:47
【问题描述】:

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

按照here in Spring blog 的建议将我的静态网络资源放入“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 中?

【问题讨论】:

标签: spring-mvc spring-security spring-boot


【解决方案1】:

有几点需要注意:

  • 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 时,您可能需要考虑使用其默认值而不是添加额外的配置。默认情况下,Spring Boot 将允许访问 /css/**/js/**/images/**/**/favicon.ico。例如,您可以拥有一个名为 src/main/resources/public/images/hello.jpg 的文件,并且无需添加任何额外配置,无需登录即可在 http://localhost:8080/images/hello.jpg 访问它。您可以在允许访问的 web method security smoke test 中看到这一点到 Bootstrap CSS 文件,无需任何特殊配置。

【讨论】:

  • - 我已经克隆了 spring boot 示例 repo 并运行示例(web 方法安全示例)。它不工作。 localhost:8080/css/bootstrap.min.css 被重定向到登录页面。 - 它与描述的解决方案不同。静态文件有路径:src/main/resources/static/css/
  • 如果您使用的是 Spring Boot 2,请查看 Thomas Lang 的答案
  • static 或 css js 应该在 src/main/resources/public 这里 public 文件夹是关键。谢谢
  • 我认为这是需要 http.authorizeRequests().antMatchers("/css/**").permitAll()
  • 我使用web.ignoring().antMatchers("/static/**"); 来访问静态资源,但现在spring security 不断将我重定向到css 并在登录后显示404 页面,而不是主页。主页仅在刷新后显示。我没有使用spring boot,而是仅使用带有@EnableWebSecurity注解的spring MVC和spring security来激活它。
【解决方案2】:
  @Override
      public void configure(WebSecurity web) throws Exception {
        web
          .ignoring()
             .antMatchers("/resources/**"); // #3
      }

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

【讨论】:

  • 对我也不起作用。当我从 API 加载我的静态 html 时,并在 /resources/css/main.css 中引用我的一个静态文件。 Rest API 呈现的 html 页面工作正常。但是,静态 css 不会。
【解决方案3】:

这可能同时是一个答案(对于 spring boot 2)和一个问题。 如果您使用扩展自

WebSecurityConfigurerAdapter

如果您不使用单独的安全机制,一切都会照旧吗?

在安迪·威尔金森(Andy Wilkinson)在上面的回答中指出,在较旧的 Spring Boot 版本(1.5 及以下)中,默认情况下允许使用 public/** or static/** 等位置。

所以总结这个问题/答案 - 如果您使用带有 spring security 的 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 等)。

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

Security changes in Spring Boot 2.0 M4

我希望这对某人有所帮助。 谢谢! 祝你有美好的一天!

【讨论】:

  • 我可以确认添加额外的行为我修复了它(Spring Boot 2.0.3)
  • 额外行确实有很大帮助,但我需要再添加几行才能使其正常工作。启动版本 2.0.6。 (1) .antMatchers("/", "/callback", "/login**", "/webjars/**", "/error**", "/static/**").permitAll() 和(2)registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");在 WebMvcConfigurer.addResourceHandlers() 下。
  • 非常感谢!
【解决方案4】:

经过 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/..

【讨论】:

  • 你能解释一下你在做什么,为什么? “Step1”:添加静态资源处理。 “Step2”:去除静态资源处理。
  • 如果有人使用 XML 配置,那么在 步骤 1 你可以在你的 dispatcher-servlet.xml 中使用这一行 <mvc:resources mapping="/resources/**" location="/resources/" /> 而不是创建新的 Java 配置类。
【解决方案5】:

如果您使用的是 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();
    }

您还需要拥有这个才能启用 webjars:

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

【讨论】:

  • WebMvcConfigurerAdapter 已弃用,因此您可以使用 WebMvcConfigurationSupport
【解决方案6】:
@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不会启用基本身份验证吗?
【解决方案7】:

我的 Spring Boot 应用程序遇到了同样的问题,所以我想如果我能与你们分享我的解决方案会很好。我只是简单地将 antMatchers 配置为适合特定类型的填充。就我而言,这只是 js 填充和 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 path"resources/myStyle.css" 根本不适合我。如果您的资源文件夹中有文件夹,只需将其添加到 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
猜你喜欢
  • 2016-05-04
  • 2017-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多