Spring security 重定向到状态码为 999 的页面

ala*_*ter 2 java spring-security

成功登录后,spring 重定向到/error具有以下内容的页面

{
  "timestamp" : 1586002411175,
  "status" : 999,
  "error" : "None",
  "message" : "No message available"
}
Run Code Online (Sandbox Code Playgroud)

我正在使用 spring-boot 2.2.4

我的配置:

spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
spring.mvc.servlet.load-on-startup=1
spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false
Run Code Online (Sandbox Code Playgroud)
@Configuration
public class DispatcherContextConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
    }
}
Run Code Online (Sandbox Code Playgroud)
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(WebSecurity web) {
        web.ignoring().antMatchers("/favicon.ico", "/resources/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeRequests()
                .antMatchers("/api/**").permitAll()
                .antMatchers("/registration/**").anonymous()
                .anyRequest().authenticated()
                .and()
                    .headers()
                        .defaultsDisabled()
                        .cacheControl()
                    .and()
                .and()
                    .exceptionHandling()
                        .accessDeniedPage("/errors/403")
                .and()
                    .formLogin()
                    .loginPage("/login")
                    .loginProcessingUrl("/login")
                    .failureUrl("/login?error")
                    .defaultSuccessUrl("/log") // I don't want to use force redirect here
                    .permitAll()
                .and()
                    .logout()
                    .logoutUrl("/logout")
                    .deleteCookies("JSESSIONID")
                    .invalidateHttpSession(true)
                    .logoutSuccessUrl("/login?logout")
                    .permitAll()
                .and()
                    .rememberMe()
                    .rememberMeParameter("remember-me")
                    .key("myKey");

    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

笔记:

原来该错误是由对我的静态资源之一的请求失败引起的。<script src="/resources/my-js-file.js"></script>项目中缺少登录页面。我可以通过删除丢失的资源导入来解决这个问题,但是这个问题将来可能会再次出现,所以它不是一个解决方案。

我怎样才能防止这种情况发生?

我知道我可以强制重定向到起始页面,.defaultSuccessUrl("/log", true)但我不想要这个。我也希望重定向能够正常工作,尽管没有找到任何资源。

ala*_*ter 7

浪费了很多时间后,我弄清楚发生了什么。

所以spring找不到登录页面使用的静态资源之一。但是它没有返回404此资源的状态,而是尝试呈现错误页面并将请求转发到/error. 然后 spring security 拒绝了这个请求,因为用户没有被授权。它将/error请求保存到会话(用于成功登录后重定向)并将用户重定向到登录页面。

当然,用户无法看到此重定向,因为302在后台完成的请求会返回状态。但主要问题是/error会话中保存的请求。

然后用户登录成功,spring 检查会话是否有此属性并重定向到/error页面。默认情况下,spring 假定您在静态资源中的某处有这样的页面。如果你没有这个页面,你会看到这个带有状态代码 999 的奇怪错误。

解决方案1

忽略/error安全配置中的页面:

web.ignoring().antMatchers("/favicon.ico", "/resources/**", "/error");
Run Code Online (Sandbox Code Playgroud)

所以这个请求在登录成功后不会被保存到会话中用于用户重定向。您将看到在登录页面上请求静态资源的状态代码将从302变为404

解决方案2

忽略 spring boot autoconfig 的一部分:

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
Run Code Online (Sandbox Code Playgroud)

这给出了相同的结果,但从配置中禁用了一些 bean,ErrorMvcAutoConfiguration所以要小心。

  • 就我而言,缺少 /images/favicon.ico 是一个问题。 (2认同)