【问题标题】:Spring Boot & Spring Security not serving content from /static folderSpring Boot 和 Spring Security 不提供来自 /static 文件夹的内容
【发布时间】:2016-12-29 09:12:18
【问题描述】:

我正在使用 Spring Boot 和 Spring Security 创建一个简单的 Web 应用程序。我有一个自定义过滤器来检查 x-auth-token 是否存在且有效。我在/src/main/resources/static 文件夹下有静态内容。但是,指向静态内容的 URL 也通过了自定义过滤器并且令牌验证失败。任何人都可以帮助找出我的配置错误吗?

@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private StatelessAuthenticationFilter statelessAuthenticationFilter;

    @Autowired
    private UserDetailsService userDetailsService;

    public SpringSecurityConfig() {
        super(true);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()
            .anyRequest().authenticated().and()

            // Custom Token based authentication based on the header
            .addFilterBefore(statelessAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService());
    }

    @Override
    public UserDetailsService userDetailsService() {
        return userDetailsService;
    }

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

    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setEnabled(false);
        filterRegistrationBean.setFilter(statelessAuthenticationFilter);
        return filterRegistrationBean;
    }
}

自定义过滤器:

@Component
public class StatelessAuthenticationFilter extends GenericFilterBean {

    @Value("${security.token.secret:asdfasdfasdf}")
    private String tokenSecret;

    @Autowired
    private UserRepository userRepository;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
                            throws IOException, ServletException {
        System.out.println("stateless authentication filter");
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        try {

            String token = httpRequest.getHeader(Constants.X_AUTH_TOKEN_HEADER_NAME);
            if(!StringUtils.hasText(token)) {
                throw new AuthenticationException(AirlineError.AUTHENTICATION_AUTH_TOKEN_MISSING);
            }

            JWTPayload jwtPayload = new JWTPayload();
            byte[] secret = tokenSecret.getBytes();
            DefaultJwtParser defaultJwtParser = new DefaultJwtParser();
            defaultJwtParser.setSigningKey(secret);

            Claims claims = defaultJwtParser.parseClaimsJws(token).getBody();
            jwtPayload.setEmail((String) claims.get("email"));
            jwtPayload.setExp((Long) claims.get("exp"));

            if (new DateTime(jwtPayload.getExp()).isBeforeNow()) {
                throw new AuthenticationException(AirlineError.AUTHENTICATION_AUTH_TOKEN_EXPIRED);
            }

            User user = userRepository.findOne(jwtPayload.getEmail());
            SecurityContextHolder.getContext().setAuthentication(new UserAuthentication(user.getEmail()));
            chain.doFilter(request, response);
        } catch(Exception e) {
            httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        }
    }

}

index.html/src/main/resources/static 文件夹中,但是当我从浏览器打开http://localhost:8080 时,它没有被提供。

编辑 1 我在 github 中创建了一个示例项目来复制该问题。希望这会有所帮助:

https://github.com/mgooty/spring-boot-security

当我击中时:

  1. http://localhost:8080http://localhost:8080/index.html 我得到 An Authentication object was not found in the SecurityContext
  2. http://localhost:8080/static/index.html我收到 404 错误

【问题讨论】:

  • 您想保护所有静态内容吗?

标签: spring spring-security spring-boot


【解决方案1】:

如果您想允许对静态内容的所有访问,那么只需在您的安全配置中进行配置:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()
            .antMatchers("/index.html").permitAll()
            .anyRequest().authenticated().and()

            // Custom Token based authentication based on the header
            .addFilterBefore(statelessAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
    }

但是,由于您的自定义安全过滤器中存在错误,这在您的情况下不起作用。但是您仍然可以为 index.html 文件或其他静态资源禁用所有网络安全(禁用所有过滤器)。

只是改变:

web.ignoring().antMatchers("/auth");

到:

web.ignoring().antMatchers("/auth", "/index.html");

请记住,您的应用程序将 /src/main/resources/static 目录映射到 / url(您的资源 url 中没有 /static 前缀)。

【讨论】:

  • 添加 permitAll() 不允许我以不安全的方式访问静态内容。我已经用更多详细信息和指向示例 GitHub 项目的链接编辑了该问题以复制该问题。谢谢。
猜你喜欢
  • 2016-05-17
  • 2019-10-20
  • 1970-01-01
  • 2021-06-19
  • 2016-07-14
  • 2019-03-30
  • 2015-09-21
  • 2020-10-24
  • 1970-01-01
相关资源
最近更新 更多