无法在 Spring Security 中加载静态内容

Posted

技术标签:

【中文标题】无法在 Spring Security 中加载静态内容【英文标题】:Unable to load static content in spring security 【发布时间】:2019-03-04 03:08:08 【问题描述】:

我已经从这个来源构建了一个基本的 spring 身份验证服务: https://spring.io/guides/gs/securing-web/

尝试使用 *** 上的几乎所有解决方案从本地文件夹中包含 JS 文件,但我做不到。当 html 页面加载时,它会说: "Uncaught ReferenceError: myFunction is not defined"

这是我的 home.html 脚本:

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Spring Security Example</title>
        <script type="javascript" src="test.js"></script>
    </head>
    <body onload="myFunction()">
        <h1>Welcome!</h1>

        <p>Click <a href="/hello">here</a> to see a greeting.</p>
    </body>
</html>

这是我的 js 文件所在的位置,htmls 放在模板文件夹中。

这是我的 mvcConfig 代码:

package hello;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;


@Configuration
public class MvcConfig implements WebMvcConfigurer 

    public void addViewControllers(ViewControllerRegistry registry) 
        registry.addViewController("/home").setViewName("home");
        registry.addViewController("/").setViewName("home");
        registry.addViewController("/hello").setViewName("redirect:http://localhost:3000/home.html");
        registry.addViewController("/login").setViewName("login");
    

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) 
    if (!registry.hasMappingForPattern("/webjars/**")) 
        registry.addResourceHandler("/webjars/**").addResourceLocations(
                "classpath:/META-INF/resources/webjars/");
    
    if (!registry.hasMappingForPattern("/**")) 
        registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/", "classpath:/resources/","classpath:/static/", "classpath:/public/");
    

    registry.addResourceHandler("/resources/**")
        .addResourceLocations("/resources/");





WebSecurityConfig 代码:

package hello;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 
    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
            .authorizeRequests()
                .antMatchers("/", "/home","/resources/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    

@Bean
@Override
public UserDetailsService userDetailsService() 
    UserDetails user =
         User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build();

    return new InMemoryUserDetailsManager(user);

【问题讨论】:

如果文件在不同的文件夹中,test.js 的 src 不仅仅是 test.js。将路径更改为src="../test.js" 可能已经是答案了。 我试过了,但没用.. 当我直接在chrome中打开html时,它会正常加载js文件。但是当从应用程序调用该 html 时,它会抛出此错误 【参考方案1】:

无论src/main/resources是什么文件夹,你都可以这样配置,在你的安全配置类中创建这个方法,一般我们把静态资源放在src/main/resources里面的static文件夹中。

//this method allows static resources to be neglected by spring security
        @Override
        public void configure(WebSecurity web) throws Exception 
            web
                .ignoring()
                .antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/images/**","/assets/**","/fonts/**","/dis/**","/vendor1/**");
        

【讨论】:

你应该使用 websecurity 而不是 httpsecurity ,这个解决方案肯定会起作用-更多你可以看到这个答案 -***.com/a/28272347/7849549 将我的脚本路径更改为: 并更改了我的 WebSecurityConfig 但它不起作用 @AjayKarri 在 src/main/resource 中创建一个静态文件夹,将你所有的 css 放在那里,默认情况下它会查找静态文件夹,所以如果你有 static/js/style.js 你可以写 也删除 -js 之前的斜线 脚本> 感谢您的时间和解决方案。我尝试混合您的两种解决方案并进行了更多更改。然后它起作用了:)【参考方案2】:

WebSecurityConfig 类中,您将permitAll 设置为仅'/''/home''/resources/**'。匿名用户无需安全检查即可访问这三个端点。

对于test.js文件,src指向当前url中的test.js。因此,当您在 localhost 上运行它时,浏览器会尝试将 test.js 查找为 http://localhost:port/current-page-url/test.js

例如,如果页面在/home 下,则浏览器调用http://localhost:8080/home/test.js,但正如您在WebSecurityConfig 中定义的那样,除了/home 本身之外的任何调用都将被Spring Security 阻止。 (/home/home/**不一样)

所以你需要做的是将src url更改为&lt;script src="/resources/test.js"&gt;&lt;/script&gt;因为/resources/**端点下的任何东西都可以被任何人访问并且它已经在MvcConfig的resourceHandler配置中注册

    registry.addResourceHandler("/resources/**")
    .addResourceLocations("classpath:/");

希望这会有所帮助!快乐编码:)

添加:

此外,在&lt;script&gt; 标记中,您应该将type 属性更改为text/javascript,或者您可以删除该属性,它会起作用。

【讨论】:

我已经尝试过这个解决方案,但没有成功。让我再试一次并确认 别忘了在开头加上/指向类路径 不工作.. 它说:

Whitelabel 错误页面

此应用程序没有明确的 /error 映射,因此您将其视为后备。

2018 年 9 月 28 日星期五 12:58:49 IST 2018 出现意外错误(类型=内部服务器错误,状态=500)。模板解析时出错(模板:“类路径资源 [templates/home.html]”- 第 5 行,第 3 列)跨度>
Ajay 如果 test.js 文件在资源文件夹中,那么您应该将 resourceLocation 指向 .addResourceLocations("classpath:/") 或者正如 Jai 所提到的,您可以将所有静态文件放在 /resources/static 文件夹中来组织它们和.addResourceLocations("classpath:/static") 谢谢 koo.. 更新这个已经解决了我一半的问题。 registry.addResourceHandler("/**") .addResourceLocations("classpath:/");

以上是关于无法在 Spring Security 中加载静态内容的主要内容,如果未能解决你的问题,请参考以下文章

无法在tomcat中加载静态文件

Spring,无法在测试中加载 ApplicationContext

spring - @ContextConfiguration 无法在 src/test/resources 中加载配置文件

MonoTouch <--> 静态库异常:无法在包中加载 NIB

无法在 Spring Boot 中加载外部属性

在静态文件中加载图像