Spring 安全性重定向到状态码为 999 的页面

问题描述 投票:0回答:3

登录成功后,spring重定向到

/error
页面,内容如下

{
  "timestamp" : 1586002411175,
  "status" : 999,
  "error" : "None",
  "message" : "No message available"
}

我正在使用

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

@Configuration
public class DispatcherContextConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
    }
}

@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");

    }

    // ...
}

注:

事实证明该错误是由于对我的静态资源之一的请求失败引起的。登录页面有项目中缺少的

<script src="/resources/my-js-file.js"></script>
。 我可以通过删除缺少的资源导入来解决此问题,但问题可能会在将来再次出现,因此这不是解决办法。

如何防止这种情况发生?

我知道我可以用

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

java spring-security
3个回答
17
投票

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

所以spring找不到登录页面使用的静态资源之一。但它不会返回此资源的状态

404
,而是尝试呈现错误页面并将请求转发到
/error
。然后 Spring Security 拒绝此请求,因为用户未获得授权。它将
/error
请求保存到会话(用于成功登录后重定向)并将用户重定向到登录页面。

当然,用户看不到此重定向,因为状态

302
返回的是在后台完成的请求。但主要问题是
/error
请求保存在会话中。

然后用户登录成功,Spring 检查会话中的此属性并重定向到

/error
页面。默认情况下,spring 假设您在静态资源中的某处有这样的页面。如果您没有此页面,您将看到这个奇怪的错误,状态代码为 999。

解决方案1

忽略安全配置中的

/error
页面:

web.ignoring().antMatchers("/favicon.ico", "/resources/**", "/error");

所以登录成功后,该请求不会保存到会话中以供用户重定向。您将看到在登录页面上请求静态资源的状态代码将从

302
更改为
404

解决方案2

忽略部分 Spring Boot 自动配置:

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration

这给出了相同的结果,但从配置中禁用了一些bean

ErrorMvcAutoConfiguration
所以要小心。


0
投票

我也有同样的问题。我尝试评论每个样式表链接以查看哪个链接导致了错误。这是我的自定义 css 文件。问题是,在我的 css 文件中,我有一个不存在的图像的 url,并且还有另一个错误的 @import 语句。评论完这些后,一切正常。


0
投票

我有相同的问题,authenticatedpermitAllrequestMatchers路径在正确的情况下具有状态代码200,但有例外情况:404或500转换为401。经过调查,我发现了与https:/相同的解决方案/stackoverflow.com/a/61029341/2260704 但我认为这是一种解决方法,在与其他开发人员讨论后,我了解到问题出在我的 SecurityConfiguration 定义中,路径规则逻辑中存在问题。

要记住的规则:在 Spring Security 中,默认情况下所有路径都是拒绝的。

您必须使用 .anyRequest() 为 requestMatcher 提供特定路径和一般情况。这样,anyRequest就支持“/error”了!

好的规则,“/error”包含在anyRequest中,(404是404,500是500):

.requestMatchers("/api/public/**").permitAll()
.anyRequest().authenticated());

错误规则:

.requestMatchers("/api/public/**").permitAll()
.requestMatchers("/api/**").authenticated());
© www.soinside.com 2019 - 2024. All rights reserved.